-
Notifications
You must be signed in to change notification settings - Fork 1.1k
-
When creating a repository that extends the DefaultKeyValueRepository, there is no option with regard to the class name of the repo.
You'll notice at that point, a class name of "_kvModel" is assigned to the KeyValueModel. We use loopback-connector-kv-redis; which leverages the loopback-connector ModelKeyComposer to prefix all redis keys with "_kvModel:"
While that's supposed to "prevent" collisions, it also means you can't use the same key for different sets of data. For example:
We use a guid as the id of our users. We store permissions for the user in combination with JWT authentication in redis. The data can be found redis as "_kvModel:guid". On the front-end, we're using nextjs and getServerSideProps to store/retrieve a different set of session data in redis...but want to use the user's ID as the key. (FWIW, we're using a shared redis instance in AWS so both the api and the front end servers can access the data) The purpose is to minimize repetitive API calls to the loopback api as the user browses the site. Ideally, the data should be set by loopback at the time they log in. Something like this:
- Verify credentials
- Retrieve the user's permission data
- Store the permissions info in redis (with the user's id)
- Set the JWT header
- Store different user information in redis (also using the user's id)
- Set the user's id as the session id in a cookie
- Return true or false for successful login
The collision occurs when we try to set the 2nd set of user information in redis...because the connector doesn't let us choose a className.
My suggestion would be to have an optional className in the constuctor for the kv.repository.bridge.ts as follows:
// @loopback/repository/src/repositories/kv.repository.bridge.ts constructor( private entityClass: typeof Model & {prototype: T}, ds: juggler.DataSource, className?:string, ) { // KVModel class is placeholder to receive methods from KeyValueAccessObject // through mixin this.kvModelClass = ds.createModel<typeof juggler.KeyValueModel>(`${className ? className : '_kvModel'}`); }
In our own repository definitions, it could look like this:
// src/repositories/session.repository.ts import { inject } from '@loopback/core'; import { DefaultKeyValueRepository } from '@loopback/repository'; import { RedisDataSource } from '../datasources'; import { Session } from '../models'; export class SessionRepository extends DefaultKeyValueRepository<Session> { constructor( @inject('datasources.redis') dataSource: RedisDataSource, ) { super(Session, dataSource, 'customClassName'); } }
// src/repositories/permissions.repository.ts import { inject } from '@loopback/core'; import { DefaultKeyValueRepository } from '@loopback/repository'; import { RedisDataSource } from '../datasources'; import { Permissions } from '../models'; export class PermissionsRepository extends DefaultKeyValueRepository<Permissions> { constructor( @inject('datasources.redis') dataSource: RedisDataSource, ) { //no third argument, so this would default to "_kvModel" as the class Name super(Session, dataSource); } }
I think this would be useful in cases where someone may want to use a keyvalue datasource for multiple types of data where there could be key collisions. I'm sure our use case can be worked around but I wanted to make the suggestion.
Beta Was this translation helpful? Give feedback.