mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
feat(server): job system (#10134)
This commit is contained in:
77
packages/backend/server/src/base/job/queue/scanner.ts
Normal file
77
packages/backend/server/src/base/job/queue/scanner.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||||
|
||||
import { ModuleScanner } from '../../nestjs';
|
||||
import { getJobHandlerMetadata } from './def';
|
||||
|
||||
interface JobHandler {
|
||||
name: string;
|
||||
fn: (payload: any) => any;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class JobHandlerScanner implements OnModuleInit {
|
||||
private readonly handlers: Record<string, JobHandler> = {};
|
||||
|
||||
constructor(private readonly scanner: ModuleScanner) {}
|
||||
|
||||
async onModuleInit() {
|
||||
this.scan();
|
||||
}
|
||||
|
||||
getHandler(jobName: JobName): JobHandler | undefined {
|
||||
return this.handlers[jobName];
|
||||
}
|
||||
|
||||
private scan() {
|
||||
const providers = this.scanner.getAtInjectables();
|
||||
|
||||
providers.forEach(wrapper => {
|
||||
const { instance, name } = wrapper;
|
||||
if (!instance || wrapper.isAlias) {
|
||||
return;
|
||||
}
|
||||
|
||||
const methods = this.scanner.getAllMethodNames(instance);
|
||||
|
||||
methods.forEach(method => {
|
||||
const fn = instance[method];
|
||||
|
||||
let jobNames = getJobHandlerMetadata(instance[method]);
|
||||
|
||||
if (jobNames.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const signature = `${name}.${method}`;
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error(`Job handler [${signature}] is not a function.`);
|
||||
}
|
||||
|
||||
if (!wrapper.isDependencyTreeStatic()) {
|
||||
throw new Error(
|
||||
`Provider [${name}] could not be RequestScoped or TransientScoped injectable if it contains job handlers.`
|
||||
);
|
||||
}
|
||||
|
||||
jobNames.forEach(jobName => {
|
||||
if (this.handlers[jobName]) {
|
||||
throw new Error(
|
||||
`Job handler ${jobName} already defined in [${this.handlers[jobName].name}].`
|
||||
);
|
||||
}
|
||||
|
||||
this.handlers[jobName] = {
|
||||
name: signature,
|
||||
fn: (payload: any) => {
|
||||
// NOTE(@forehalo):
|
||||
// we might create spies on the job handlers when testing,
|
||||
// avoid reusing `fn` variable to fail the spies or stubs
|
||||
return instance[method].bind(instance)(payload);
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user