diff --git a/src/@loafer/ng-rpc/core/error.ts b/src/@loafer/ng-rpc/core/error.ts new file mode 100644 index 0000000..f90aac7 --- /dev/null +++ b/src/@loafer/ng-rpc/core/error.ts @@ -0,0 +1,6 @@ +export class SubscriberParameterError extends Error { + public constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} diff --git a/src/@loafer/ng-rpc/core/index.ts b/src/@loafer/ng-rpc/core/index.ts index 6b36029..d97df57 100644 --- a/src/@loafer/ng-rpc/core/index.ts +++ b/src/@loafer/ng-rpc/core/index.ts @@ -1 +1,2 @@ +export * from './error'; export * from './token'; diff --git a/src/@loafer/ng-rpc/subscribe/subscribe.service.ts b/src/@loafer/ng-rpc/subscribe/subscribe.service.ts index ab86fb1..c26512e 100644 --- a/src/@loafer/ng-rpc/subscribe/subscribe.service.ts +++ b/src/@loafer/ng-rpc/subscribe/subscribe.service.ts @@ -3,12 +3,14 @@ import { Store, select } from '@ngrx/store'; import { Type, + PropertyKeyType, } from '@loafer/core'; import { TypeUtil } from '@loafer/core/util/TypeUtil'; import { Class, + Method, Metadata, } from '@loafer/core/reflect'; @@ -17,14 +19,26 @@ import { RPCSubscriberDecorator } from '../decorator'; import { RPCClientNotificationCodec, } from '../protocol'; +import { SubscriberParameterError } from '../core'; + +export interface SubscriberMethod { + className: PropertyKeyType; + methodName: PropertyKeyType; + parameterTypes: string[]; + + method: Method; + instance: any; +} @Injectable() export class RPCSubscribeService { private subscribers: Set; + private subscriberMethodMap: Map; constructor( ) { this.subscribers = new Set(); + this.subscriberMethodMap = new Map(); } public addSubscriber(subscriber: Type): void { @@ -46,11 +60,100 @@ export class RPCSubscribeService { const methods = clazz.getMethods(); methods.forEach((method, propertyKey) => { const annon = method.getAnnotation(RPCSubscriberDecorator); - console.log(`subscriber method[${annon.attribute.method}]`); + if (undefined === annon) { + return; + } + + const subscriberMethodName = annon.attribute.method; + let subscriberMethods: SubscriberMethod[] = this.subscriberMethodMap.get(subscriberMethodName); + if (undefined === subscriberMethods) { + subscriberMethods = []; + this.subscriberMethodMap.set(subscriberMethodName, subscriberMethods); + } + + const paramTypes = this.getParamTypes(method); + + const subscriberMethod: SubscriberMethod = { + className: clazz.getName(), + methodName: method.getName(), + parameterTypes: paramTypes, + method: method, + instance: subscriber, + }; + + subscriberMethods.push(subscriberMethod); }); } public notify(codec: RPCClientNotificationCodec): void { - console.log(`notify method[${codec.method()}] params[${codec.params()}]`); + const method = codec.method(); + const params = codec.params(); + + const subscriberMethods: SubscriberMethod[] = this.subscriberMethodMap.get(method); + if (undefined === subscriberMethods) { + console.warn(`Subscriber for method[${method}] is not exist`); + return; + } + subscriberMethods.forEach((subscriberMethod) => { + try { + const args = this.converParams(params, subscriberMethod.parameterTypes); + subscriberMethod.method.invoke(subscriberMethod.instance, ...args); + } catch (error) { + console.error(error); + } + }); + } + + private getParamTypes(method: Method): string[] { + if (undefined === method || null === method || 0 === method.getParameterCount()) { + return []; + } + + const parameters = method.getParameters(); + const results: string[] = []; + for (let indexI = 0; indexI < parameters.length; indexI++) { + const paramType = parameters[indexI].getType(); + results.push(paramType.name); + } + return results; + } + + private converParams(params: string[], paramTypes: string[]): any[] { + const results: any[] = []; + + if (undefined === params || null === params || 0 === params.length) { + return results; + } + if (undefined === paramTypes || null === paramTypes || 0 === paramTypes.length) { + return results; + } + if (params.length !== paramTypes.length) { + throw new SubscriberParameterError(`Count is not same from server[${params.length}] and method[${paramTypes.length}]`); + } + for (let indexI = 0; indexI < params.length; indexI++) { + const param = params[indexI]; + const type = paramTypes[indexI]; + switch (type) { + case 'Object': + case 'Array': + case 'Map': + results.push(JSON.parse(param)); + break; + case 'String': + results.push(param); + break; + case 'Number': + results.push(Number(param)); + break; + case 'Boolean': + results.push(Boolean(param)); + break; + case 'Function': + throw new SubscriberParameterError(`Function type [${indexI}] is not allowed`); + default: + throw new SubscriberParameterError(`${type} type parameter[${indexI}] is not allowed`); + } + } + return results; } } diff --git a/src/packages/discovery/component/setting/setting.component.ts b/src/packages/discovery/component/setting/setting.component.ts index b8d514e..49fd321 100644 --- a/src/packages/discovery/component/setting/setting.component.ts +++ b/src/packages/discovery/component/setting/setting.component.ts @@ -9,9 +9,9 @@ import { } from '../../model'; import * as CIDR from 'ip-cidr'; import * as DiscoveredStore from '../../store/setting'; -import * as DiscoverStore from '../../store/notification'; +import * as DiscoverStore from '../../store/discover'; -import { SettingSelector, NotificationSelector } from '../../store'; +import { SettingSelector, DiscoverSelector } from '../../store'; @Component({ selector: 'of-setting', @@ -21,7 +21,7 @@ import { SettingSelector, NotificationSelector } from '../../store'; export class SettingComponent implements OnInit, AfterContentInit { settingSucceed$ = this.discoverdstore.pipe(select(SettingSelector.select('isStart'))); - discoveryResult$ = this.discoverstore.pipe(select(NotificationSelector.select('getDiscoveryResult'))); + discoveryResult$ = this.discoverstore.pipe(select(DiscoverSelector.select('getDiscoveryResult'))); started = false; diff --git a/src/packages/discovery/store/notification/notification.action.ts b/src/packages/discovery/store/discover/discover.action.ts similarity index 86% rename from src/packages/discovery/store/notification/notification.action.ts rename to src/packages/discovery/store/discover/discover.action.ts index 62fedb3..f25e152 100644 --- a/src/packages/discovery/store/notification/notification.action.ts +++ b/src/packages/discovery/store/discover/discover.action.ts @@ -16,10 +16,11 @@ import { DiscoverHost = '[discovery.discovery] discoverHost', DiscoverPort = '[discovery.discovery] discoverPort', DiscoverService = '[discovery.discovery] discoverService', - DiscoveredZone = '[@@NOTIFICATION] DiscoveryService.discoveredZone', - DiscoveredHost = '[@@NOTIFICATION] DiscoveryService.discoveredHost', - DiscoveredPort = '[@@NOTIFICATION] DiscoveryService.discoveredPort', - DiscoveredService = '[@@NOTIFICATION] DiscoveryService.discoveredService', + + DiscoveredZone = '[discovery.discovery] DiscoveryService.discoveredZone', + DiscoveredHost = '[discovery.discovery] DiscoveryService.discoveredHost', + DiscoveredPort = '[discovery.discovery] DiscoveryService.discoveredPort', + DiscoveredService = '[discovery.discovery] DiscoveryService.discoveredService', } export class DiscoverZone implements Action { diff --git a/src/packages/discovery/store/notification/notification.effect.spec.ts b/src/packages/discovery/store/discover/discover.effect.spec.ts similarity index 75% rename from src/packages/discovery/store/notification/notification.effect.spec.ts rename to src/packages/discovery/store/discover/discover.effect.spec.ts index 4bbc6cf..f868840 100644 --- a/src/packages/discovery/store/notification/notification.effect.spec.ts +++ b/src/packages/discovery/store/discover/discover.effect.spec.ts @@ -1,8 +1,8 @@ import { TestBed, inject } from '@angular/core/testing'; -import { Effects } from './notification.effect'; +import { Effects } from './discover.effect'; -describe('Notification.Effects', () => { +describe('Discover.Effects', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [Effects] diff --git a/src/packages/discovery/store/notification/notification.effect.ts b/src/packages/discovery/store/discover/discover.effect.ts similarity index 98% rename from src/packages/discovery/store/notification/notification.effect.ts rename to src/packages/discovery/store/discover/discover.effect.ts index e3aa0c9..0fd5078 100644 --- a/src/packages/discovery/store/notification/notification.effect.ts +++ b/src/packages/discovery/store/discover/discover.effect.ts @@ -20,7 +20,7 @@ import { DiscoverPort, DiscoverService, ActionType -} from './notification.action'; +} from './discover.action'; import {DiscoveryService} from '../../service/discovery.service'; diff --git a/src/packages/discovery/store/notification/notification.reducer.ts b/src/packages/discovery/store/discover/discover.reducer.ts similarity index 93% rename from src/packages/discovery/store/notification/notification.reducer.ts rename to src/packages/discovery/store/discover/discover.reducer.ts index 276bb66..6c4d839 100644 --- a/src/packages/discovery/store/notification/notification.reducer.ts +++ b/src/packages/discovery/store/discover/discover.reducer.ts @@ -1,12 +1,12 @@ import { Actions, ActionType, -} from './notification.action'; +} from './discover.action'; import { State, initialState, -} from './notification.state'; +} from './discover.state'; import { Zone, @@ -19,7 +19,9 @@ export function reducer(state = initialState, action: Actions): State { switch (action.type) { case ActionType.DiscoveredZone: { const zone: Zone = action.payload; - state.zones.set(zone.network, zone); + const zones: Map = null === state.zones ? new Map() : state.zones; + + zones.set(zone.network, zone); return state; } diff --git a/src/packages/discovery/store/notification/notification.state.ts b/src/packages/discovery/store/discover/discover.state.ts similarity index 100% rename from src/packages/discovery/store/notification/notification.state.ts rename to src/packages/discovery/store/discover/discover.state.ts diff --git a/src/packages/discovery/store/discover/index.ts b/src/packages/discovery/store/discover/index.ts new file mode 100644 index 0000000..cdd131c --- /dev/null +++ b/src/packages/discovery/store/discover/index.ts @@ -0,0 +1,4 @@ +export * from './discover.action'; +export * from './discover.reducer'; +export * from './discover.state'; +export * from './discover.effect'; diff --git a/src/packages/discovery/store/index.ts b/src/packages/discovery/store/index.ts index cf50576..d54fd4a 100644 --- a/src/packages/discovery/store/index.ts +++ b/src/packages/discovery/store/index.ts @@ -10,30 +10,30 @@ import { StateSelector } from 'packages/core/ngrx/store'; import { MODULE } from '../discovery.constant'; -import * as NotificationStore from './notification'; +import * as DiscoverStore from './discover'; import * as SettingStore from './setting'; export interface State { - notification: NotificationStore.State; + discover: DiscoverStore.State; setting: SettingStore.State; } export const REDUCERS = { - notification: NotificationStore.reducer, + discover: DiscoverStore.reducer, setting: SettingStore.reducer, }; export const EFFECTS = [ SettingStore.Effects, - NotificationStore.Effects, + DiscoverStore.Effects, ]; export const selectDiscoveryState = createFeatureSelector(MODULE.name); -export const NotificationSelector = new StateSelector(createSelector( +export const DiscoverSelector = new StateSelector(createSelector( selectDiscoveryState, - (state: State) => state.notification + (state: State) => state.discover )); export const SettingSelector = new StateSelector(createSelector( diff --git a/src/packages/discovery/store/notification/index.ts b/src/packages/discovery/store/notification/index.ts deleted file mode 100644 index 76ee543..0000000 --- a/src/packages/discovery/store/notification/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './notification.action'; -export * from './notification.reducer'; -export * from './notification.state'; -export * from './notification.effect'; diff --git a/src/packages/discovery/subscriber/discovery.subscriber.ts b/src/packages/discovery/subscriber/discovery.subscriber.ts index abe430e..7149a4d 100644 --- a/src/packages/discovery/subscriber/discovery.subscriber.ts +++ b/src/packages/discovery/subscriber/discovery.subscriber.ts @@ -3,7 +3,7 @@ import { Store, select } from '@ngrx/store'; import { RPCSubscriber } from '@loafer/ng-rpc/decorator'; -import * as DiscoveryStore from '../store/notification'; +import * as DiscoverStore from '../store/discover'; import { Zone, @@ -16,24 +16,28 @@ import { export class DiscoverySubscriber { public constructor( - private store: Store, + private store: Store, ) { } @RPCSubscriber({method: 'DiscoveryService.discoveredZone'}) public discoveredZone(zone: Zone): void { - this.store.dispatch(new DiscoveryStore.DiscoveredZone(zone)); + console.log(`DiscoverySubscriber.discoveredZone zone:${zone}`); + + this.store.dispatch(new DiscoverStore.DiscoveredZone(zone)); } @RPCSubscriber({method: 'DiscoveryService.discoveredHost'}) public discoveredHost(host: Host): void { - this.store.dispatch(new DiscoveryStore.DiscoveredHost(host)); + console.log(`DiscoverySubscriber.discoveredHost host:${host}`); + + this.store.dispatch(new DiscoverStore.DiscoveredHost(host)); } @RPCSubscriber({method: 'DiscoveryService.discoveredPort'}) public discoveredPort(port: Port): void { - this.store.dispatch(new DiscoveryStore.DiscoveredPort(port)); + this.store.dispatch(new DiscoverStore.DiscoveredPort(port)); } @RPCSubscriber({method: 'DiscoveryService.discoveredService'}) public discoveredService(service: Service): void { - this.store.dispatch(new DiscoveryStore.DiscoveredService(service)); + this.store.dispatch(new DiscoverStore.DiscoveredService(service)); } }