I'm trying out a event sourced NestJS application. I'm stuck at the following point: In my GamesModule I'm setting up the Eventstore connection to my stream. In these options there are write and read functions which are called by the library to update/ read the stream's last checkpoint position. I'd like to call my service methods that write and read to/from the database from these functions.
I've tried injecting the service in the constructor, but because the register function is and has to be a static method, I don't have access to whatever is injected in the constructor.
Is it possible to use a service or repository in the Dynamic module's options?
Service writing to and reading from DB:
@Injectable()
export class EventStoreStateService {
private readonly logger = new Logger(EventStoreStateService.name);
constructor(
@InjectRepository(EventStoreState)
private eventStoreStateRepository: Repository<EventStoreState>,
) {}
updateCheckpoint(stream: string, position: number) {
const updated = this.eventStoreStateRepository.update(
{ lastCheckpoint: position },
{ streamName: stream },
);
this.logger.log({ updated });
return updated;
}
getLastCheckpoint(stream: string) {
const last = this.eventStoreStateRepository.findOne({
where: { streamName: stream },
});
this.logger.log({ last });
return last;
}
}
The module where I setup the event-store connection. In the useFactory
store.write(key: string, value: number)
I'd like to call my service methods
@Module({
imports: [EventStoreStateModule],
})
export class GamesModule {
constructor(
// no access to this service in the static method
//
@Inject(EventStoreStateService)
private readonly eventStoreStateService: EventStoreStateService,
) {}
static register(): // updateCheckpoint: (key: string, value: number) => Promise<number>,
// getLastCheckpoint: (key: string) => Promise<number>,
DynamicModule {
return {
module: GamesModule,
imports: [
CqrsModule,
EventStoreModule.registerFeatureAsync({
type: 'event-store',
useFactory: async (...args) => {
console.log({ args });
return {
featureStreamName: '$ce-game',
type: 'event-store',
subscriptions: [
{
type: EventStoreSubscriptionType.CatchUp, // research various types
stream: '$ce-game',
resolveLinkTos: true,
},
],
eventHandlers: EventStoreInstanciators,
store: {
storeKey: 'game',
write: async (key: string, value: number) => {
// TODO: on every new event for stream x this function
// is called with the last position number
// problem: we need access to the service that connects
// to ORM, but it's a static method so no access to whatever
// is injected in the constructor
//
},
read: async (key: string) => {
// same as write function
//
},
clear: () => null,
},
};
},
}),
TypeOrmModule.forFeature([GameProjection]),
],
controllers: [GamesController],
providers: [
GamesResolver,
GamesService,
GamesRepository,
...CommandHandlers,
...EventHandlers,
],
};
}
}
Using this library for event-store connection: https://github.com/juicycleff/nestjs-event-store.
Key things to know in NestJs.
constructor( private readonly eventStoreStateService: EventStoreStateService){}
exports: [EventStoreStateService]
and then also inject in service or controller where you want to use it.