alexdonh / tsed-bee-queue

Bee-queue for Ts.ED framework
MIT License
4 stars 0 forks source link

[TECH] Ts.ED can inject multiple providers on contructor by using type field #2

Open Romakita opened 1 year ago

Romakita commented 1 year ago

Since v6.129.0, Ts.ED can inject multiple provider on the constructor, by given a token group :)

Here is the doc reference: https://tsed.io/docs/providers.html#inject-many-provider

In you case:

@Module({
  imports: [RedisService]
})
export class QueueModule implements OnReady, OnDestroy {
   constructor(@Inject(PROVIDER_TYPE_QUEUE) protected queues: QueueProvider[];

   $onReady() {
       this.queues.forEach((instance) => {
            const provider = this.injector.getProvider(classOf(instance));

            if (!instance.$queue) { // allow service to access to queue instance ? if not interesting keep provider.queue but it potentially dangerous, because a same provider can have multiple instance depending on his ProviderScope
               instance.$queue = this.make(instance, this.getQueueMetadata(provider.token));
           } else {
             // throw error or just log a warning
           }
       })     
   }

    private make(instance: QueueProvider, metadata ) {
      const {name, hostId, ...options} = metadata;

      const queue = this.queueService.get(name, hostId, options);

      queue.process(metadata.concurrency, instance.$exec.bind(instance));

      if (instance.$failed) {
        queue.on("failed", instance.$failed.bind(instance));
      }

      if (instance.$succeeded) {
        queue.on("succeeded", instance.$succeeded.bind(instance));
      }

      return queue;
    }
}

https://github.com/alexdonh/tsed-bee-queue/blob/f662d9e7a4f06f81113314bd3573cd3424ce7a02/src/QueueModule.ts#L25

You need to replace PROVIDER_TYPE_QUEUE = "queue" by PROVIDER_TYPE_QUEUE = Symbol("queue").

Another point, creating registry isn't necessary in this case.

instead of:

import {GlobalProviders, Provider} from "@tsed/di";

export const PROVIDER_TYPE_QUEUE = "queue";

export const QueueRegistry = GlobalProviders.createRegistry(PROVIDER_TYPE_QUEUE, Provider, {
  injectable: true
});

export const registerQueue = GlobalProviders.createRegisterFn(PROVIDER_TYPE_QUEUE);

Do that:

import {StoreSet, useDecorators} from "@tsed/core";
import {QueueOptions} from "../interfaces/QueueOptions";

export function Queue(options: QueueOptions): ClassDecorator {
  return useDecorators(Injectable({type: PROVIDER_TYPE_QUEUE}) , StoreSet("queue", options)) as any;
}

This code create automatically the provider PROVIDER_TYPE_QUEUE type :)

alexdonh commented 1 year ago

@Romakita managed to spend some time updating the code with bumping all new versions and quite a few code refactoring. I did it a little different to what you suggested though. But I did use inject multiple provider and it works like a charm!

Also I see that some typechecks don't seem to correct i.e. injector.getAll and inject.getProviders should accept more than just string (given that we use symbol)

Feel free to have a look. I'd welcome all suggestions!