Skip to content

Commit

Permalink
feat: add getEggObjects API to fetch all instances
Browse files Browse the repository at this point in the history
  • Loading branch information
sang4lv committed Jan 31, 2024
1 parent ab7f54d commit d96f026
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 12 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -934,14 +934,35 @@ import { EggObjectFactory } from '@eggjs/tegg';
export class HelloService {
@Inject()
private readonly eggObjectFactory: EggObjectFactory;

async hello(): Promise<string> {
const helloImpl = await this.eggObjectFactory.getEggObject(AbstractHello, HelloType.BAR);
return helloImpl.hello();
}
}
```

动态获取多个实现,通过 for/await 循环获得实例。

```ts
import { EggObjectFactory } from '@eggjs/tegg';

@ContextProto()
export class HelloService {
@Inject()
private readonly eggObjectFactory: EggObjectFactory;

async hello(): Promise<string[]> {
const helloImpls = await this.eggObjectFactory.getEggObjects(AbstractHello, HelloType.BAR);
const messages = [];
for await (const helloImpl of helloImpls) {
messages.push(helloImpl.hello());
}
return messages;
}
}
```

### 配置项目 module

一般情况下,无需在项目中手动声明包含了哪些 module,tegg 会自动在项目目录下进行扫描。但是会存在一些特殊的情况,tegg 无法扫描到,比如说 module 是通过 npm 包的方式来发布。因此 tegg 支持通过 `config/module.json` 的方式来声明包含了哪些 module。
Expand Down
29 changes: 28 additions & 1 deletion core/dynamic-inject-runtime/src/EggObjectFactory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { EggContainerFactory } from '@eggjs/tegg-runtime';
import { EggAbstractClazz, EggObjectFactory as IEggObjectFactory, QualifierImplUtil } from '@eggjs/tegg-dynamic-inject';
import { AccessLevel, PrototypeUtil, QualifierValue, SingletonProto } from '@eggjs/core-decorator';
import {
EggAbstractClazz,
EggObjectFactory as IEggObjectFactory,
QualifierImplUtil,
} from '@eggjs/tegg-dynamic-inject';

import { EGG_OBJECT_FACTORY_PROTO_IMPLE_TYPE } from './EggObjectFactoryPrototype';

@SingletonProto({
Expand All @@ -23,4 +28,26 @@ export class EggObjectFactory implements IEggObjectFactory {
const eggObject = await this.eggContainerFactory.getOrCreateEggObject(protoObj, protoObj.name);
return eggObject.obj as T;
}

async getEggObjects<T extends object>(abstractClazz: EggAbstractClazz<T>) {
const implClazzMap = QualifierImplUtil.getQualifierImpMap(abstractClazz);
const getEggObject = this.getEggObject.bind(this);
const qualifierValues = Array.from(implClazzMap.keys());

return {
[Symbol.asyncIterator]() {
return {
key: 0,
async next() {
if (this.key === qualifierValues.length) {
return { done: true } as IteratorResult<T>;
}

const value = await getEggObject(abstractClazz, qualifierValues[this.key++]);
return { value, done: false } as IteratorResult<T>;
},
};
},
};
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ContextProto, Inject } from '@eggjs/core-decorator';
import { ContextHelloType, SingletonHelloType } from './FooType';
import { EggObjectFactory } from '@eggjs/tegg-dynamic-inject';

import { AbstractContextHello } from './AbstractContextHello';
import { AbstractSingletonHello } from './AbstractSingletonHello';
import { EggObjectFactory } from '@eggjs/tegg-dynamic-inject';
import { ContextHelloType, SingletonHelloType } from './FooType';

@ContextProto()
export class HelloService {
Expand All @@ -19,4 +20,19 @@ export class HelloService {
const msgs = helloImpls.map(helloImpl => helloImpl.hello());
return msgs;
}

async sayHelloToAll(): Promise<string[]> {
const singletonHellos = await this.eggObjectFactory.getEggObjects(AbstractSingletonHello);
const contextHellos = await this.eggObjectFactory.getEggObjects(AbstractContextHello);

const msgs: string[] = [];
for await (const helloImpl of singletonHellos) {
msgs.push(helloImpl.hello());
}
for await (const helloImpl of contextHellos) {
msgs.push(helloImpl.hello());
}

return msgs;
}
}
22 changes: 19 additions & 3 deletions core/dynamic-inject-runtime/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import assert from 'assert';
import path from 'path';
import { LoadUnitInstance, LoadUnitInstanceFactory } from '@eggjs/tegg-runtime';

import { LoadUnitFactory } from '@eggjs/tegg-metadata';
import { LoadUnitInstance, LoadUnitInstanceFactory } from '@eggjs/tegg-runtime';

import { EggTestContext } from '../../test-util';
import { HelloService } from './fixtures/modules/dynamic-inject-module/HelloService';
import { CoreTestHelper } from '../../test-util/CoreTestHelper';
import assert from 'assert';
import { HelloService } from './fixtures/modules/dynamic-inject-module/HelloService';

describe('test/dynamic-inject-runtime.test.ts', () => {
let modules: Array<LoadUnitInstance>;
Expand Down Expand Up @@ -47,4 +49,18 @@ describe('test/dynamic-inject-runtime.test.ts', () => {
]);
});
});

it('should work with getAllEggObjects', async () => {
await EggTestContext.mockContext(async () => {
const helloService = await CoreTestHelper.getObject(HelloService);
const msgs = await helloService.sayHelloToAll();
assert.deepStrictEqual(msgs, [
'hello, bar(singleton:0)',
'hello, foo(singleton:0)',
'hello, bar(context:0)',
'hello, foo(context:0)',
]);
});

});
});
4 changes: 3 additions & 1 deletion core/dynamic-inject/src/EggObjectFactory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { EggAbstractClazz } from './typing';
import { QualifierValue } from '@eggjs/core-decorator';

import { EggAbstractClazz } from './typing';

export interface EggObjectFactory {
getEggObject<T extends object>(abstractClazz: EggAbstractClazz<T>, qualifierValue: QualifierValue): Promise<T>;
getEggObjects<T extends object>(abstractClazz: EggAbstractClazz<T>): Promise<AsyncIterable<T>>;
}
8 changes: 4 additions & 4 deletions core/dynamic-inject/src/QualifierImplUtil.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EggAbstractClazz } from './typing';
import { EggProtoImplClass, MetadataUtil, QualifierValue } from '@eggjs/core-decorator';

import { EggAbstractClazz } from './typing';

export const QUALIFIER_IMPL_MAP = Symbol.for('EggPrototype#qualifierImplMap');

export class QualifierImplUtil {
Expand All @@ -14,9 +15,8 @@ export class QualifierImplUtil {
return implMap?.get(qualifierValue);
}

static listQualifierImps(abstractClazz: EggAbstractClazz): EggProtoImplClass[] {
static getQualifierImpMap(abstractClazz: EggAbstractClazz): Map<QualifierValue, EggProtoImplClass> {
const implMap: Map<QualifierValue, EggProtoImplClass> | undefined = MetadataUtil.getMetaData(QUALIFIER_IMPL_MAP, abstractClazz as unknown as EggProtoImplClass);
if (!implMap) return [];
return Array.from(implMap.values());
return implMap || new Map();
}
}

0 comments on commit d96f026

Please sign in to comment.