From 14a5488d1d18048c581ad090be2370f495f458ad Mon Sep 17 00:00:00 2001 From: Idan Levin Date: Tue, 26 Dec 2017 15:27:50 +0200 Subject: [PATCH 1/2] Fix loader type + minor fixes --- index.d.ts | 4 +-- index.js.flow | 4 +-- .../services/Microservices.js | 26 ++++++++++++++----- .../services/ServiceCall.js | 4 ++- .../services/ServiceDefinition.js | 20 +------------- src/scalecube-services/services/utils.js | 3 +-- 6 files changed, 29 insertions(+), 32 deletions(-) diff --git a/index.d.ts b/index.d.ts index def19504..2ee88e89 100644 --- a/index.d.ts +++ b/index.d.ts @@ -35,7 +35,7 @@ interface Class0 { servicesConfig: ServicesConfig; build(): Microservices; - serviceLoaders(...services: Array<{loader: () => {promise: Promise}, serviceClass: any}>): Class0; + serviceLoaders(...services: Array<{loader: () => Promise, serviceClass: any}>): Class0; services(...services: Array): Class0; } export class DispatcherContext { @@ -115,7 +115,7 @@ export class ServicesConfig { servicesConfig: Array; constructor(service: any, builder?:Class0); } -declare var utils: {getServiceInterface: (o: Object) => any, getServiceName: (o: Object) => any | any | any | any | any, isLoader: (inst: Object | null) => null | any | any | boolean, makeLoader: (loadFunction: {promise: Promise}, Class: any) => {meta: any, promise: {promise: Promise}}}; +declare var utils: {getServiceInterface: (o: Object) => any, getServiceName: (o: Object) => any | any | any | any | any, isLoader: (inst: Object | null) => null | any | any | boolean, makeLoader: (loadFunction: Promise, Class: any) => {meta: any, promise: Promise}}; diff --git a/index.js.flow b/index.js.flow index ce025e62..8c41ea12 100644 --- a/index.js.flow +++ b/index.js.flow @@ -29,7 +29,7 @@ declare class Class0 { servicesConfig: ServicesConfig; build(): Microservices; - serviceLoaders(...services: Array<{loader: () => {promise: Promise}, serviceClass: any}>): Class0; + serviceLoaders(...services: Array<{loader: () => Promise, serviceClass: any}>): Class0; services(...services: Array): Class0; } declare export class DispatcherContext { @@ -109,4 +109,4 @@ declare export class ServicesConfig { servicesConfig: Array; constructor(service: any, builder: ?Class0): ServicesConfig | ServicesConfig; } -declare export var utils: {getServiceInterface: (o: Object) => any, getServiceName: (o: Object) => any | any | any | any | any, isLoader: (inst: Object | null) => null | any | any | boolean, makeLoader: (loadFunction: {promise: Promise}, Class: any) => {meta: any, promise: {promise: Promise}}}; +declare export var utils: {getServiceInterface: (o: Object) => any, getServiceName: (o: Object) => any | any | any | any | any, isLoader: (inst: Object | null) => null | any | any | boolean, makeLoader: (loadFunction: Promise, Class: any) => {meta: any, promise: Promise}}; diff --git a/src/scalecube-services/services/Microservices.js b/src/scalecube-services/services/Microservices.js index be98266d..66b820ca 100644 --- a/src/scalecube-services/services/Microservices.js +++ b/src/scalecube-services/services/Microservices.js @@ -1,21 +1,31 @@ // @flow -import { ServicesConfig, ServiceRegistery, ProxyContext, DispatcherContext, utils } from 'src/scalecube-services/services' +import { + ServicesConfig, + ServiceRegistery, + ProxyContext, + DispatcherContext, + utils +} from 'src/scalecube-services/services' class Builder { servicesConfig: ServicesConfig; - constructor(){ + + constructor() { this.servicesConfig = new ServicesConfig([]); } - services(...services:any[]){ + + services(...services: any[]) { this.servicesConfig = ServicesConfig.builder(this) .services(services) .create(); return this; } - serviceLoaders(...services:{loader:()=>{promise:Promise}, serviceClass:any}[]){ - services.map((s)=>this.services(utils.makeLoader(s.loader(), s.serviceClass))); + + serviceLoaders(...services: { loader: () => Promise, serviceClass: any }[]) { + services.map((s) => this.services(utils.makeLoader(s.loader(), s.serviceClass))); return this; } + build(): Microservices { return new Microservices(this.servicesConfig); } @@ -23,16 +33,20 @@ class Builder { export class Microservices { static Builder: Builder; serviceRegistery: ServiceRegistery; - constructor(serviceConfig: ServicesConfig){ + + constructor(serviceConfig: ServicesConfig) { this.serviceRegistery = new ServiceRegistery(serviceConfig); return this; } + static builder() { return new Builder(); }; + proxy() { return new ProxyContext(this); } + dispatcher() { return new DispatcherContext(this); } diff --git a/src/scalecube-services/services/ServiceCall.js b/src/scalecube-services/services/ServiceCall.js index fb19f7b0..dcd22ae7 100644 --- a/src/scalecube-services/services/ServiceCall.js +++ b/src/scalecube-services/services/ServiceCall.js @@ -36,10 +36,12 @@ export class ServiceCall { if (!Array.isArray(message.data)) { return reject(new Error(`Message format error: data must be Array`)); } + const inst = this.router.route(message); + if (inst && inst.service && utils.isLoader(inst)) { return inst.service.promise.then((myservice) => { - return resolve(myservice[ message.method ](...message.data)) + return resolve(myservice[ message.method ](...message.data)); }); } else if (inst) { return resolve(inst.service[ message.method ](...message.data)); diff --git a/src/scalecube-services/services/ServiceDefinition.js b/src/scalecube-services/services/ServiceDefinition.js index 2b459851..8a3bb05c 100644 --- a/src/scalecube-services/services/ServiceDefinition.js +++ b/src/scalecube-services/services/ServiceDefinition.js @@ -26,29 +26,11 @@ export class ServiceDefinition { } static from(service: Object) { const methods = {}; - //const x = new service(); - /*Object.getOwnPropertyNames(Object.getPrototypeOf(service)).map((method) => { - if (method !== 'constructor' && typeof service[ method ] === 'function') { - methods[ method ] = service[ method ]; - } - });*/ + const meta = service.constructor.meta || service.meta; Object.keys(meta.methods).map((key)=>{ methods[ key ] = ServiceDefinition.getMethod(meta, service, key); }); return new ServiceDefinition(service, utils.getServiceName(service), methods); } - /*static fromPromise(service: ServicePromise){ - const methods = {}; - - - - Object.getOwnPropertyNames(Object.getPrototypeOf(service)).map((method) => { - if (method !== 'constructor' && typeof service[ method ] === 'function') { - methods[ method ] = service[ method ]; - } - }); - - return new ServiceDefinition(service, utils.getServiceName(service), methods); - }*/ } diff --git a/src/scalecube-services/services/utils.js b/src/scalecube-services/services/utils.js index c086e07e..4d6e6a2c 100644 --- a/src/scalecube-services/services/utils.js +++ b/src/scalecube-services/services/utils.js @@ -1,7 +1,6 @@ // @flow - export const getServiceInterface = (o: Object) => { // we`ll have to think about this one... right new just a name return o.constructor.name; @@ -12,7 +11,7 @@ export const getServiceName = (o: Object) => { export const isLoader = (inst: Object | null) => { return inst && inst.service && inst.service.meta && inst.service.meta.type === 'Loader'; } -export const makeLoader = (loadFunction: {promise:Promise}, Class:any) => { +export const makeLoader = (loadFunction: Promise, Class: any) => { return { promise: loadFunction, meta: Object.assign(Class.meta, { From 4e00e8addcaa775a8fca5a32b8ff2fbba1245420 Mon Sep 17 00:00:00 2001 From: Idan Levin Date: Fri, 29 Dec 2017 01:33:17 +0200 Subject: [PATCH 2/2] Pass errors swallow by promise to the observable --- src/scalecube-services/services/ServiceCall.js | 13 +++++++++---- test/scalecube-services/services/greeting.test.js | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/scalecube-services/services/ServiceCall.js b/src/scalecube-services/services/ServiceCall.js index dcd22ae7..988f18a8 100644 --- a/src/scalecube-services/services/ServiceCall.js +++ b/src/scalecube-services/services/ServiceCall.js @@ -2,6 +2,9 @@ import { Router, Message, utils } from 'src/scalecube-services/services'; import { Observable } from 'rxjs/Observable'; +// $FlowFixMe +import 'rxjs/add/operator/catch'; + const isObservable = (obj: any): boolean => { if (obj.constructor.name === 'Observable') { @@ -60,12 +63,14 @@ export class ServiceCall { observer.error(new Error(`Service not found error: ${message.serviceName}.${message.method}`)); } else if (utils.isLoader(inst)) { let unsubscribe; - const promise = inst.service.promise; - promise.then((service) => { - unsubscribe = createServiceObserver(message, service, observer); + const promise = new Promise(resolve=>{ + inst.service.promise.then((service) => { + resolve(createServiceObserver(message, service, observer)); + }).catch(e=>observer.error(e)); + }); return () => { - promise.then(() => unsubscribe()) + promise.then(unsubscribe => unsubscribe()); }; } else { return createServiceObserver(message, inst.service, observer); diff --git a/test/scalecube-services/services/greeting.test.js b/test/scalecube-services/services/greeting.test.js index bb9dc046..efae0d13 100644 --- a/test/scalecube-services/services/greeting.test.js +++ b/test/scalecube-services/services/greeting.test.js @@ -34,7 +34,7 @@ describe('Greeting suite', () => { .create(); expect.assertions(1); - return expect().rejects.toEqual(new Error("please provide user to greet")); + return expect(greetingService.hello()).rejects.toEqual(new Error("please provide user to greet")); }); it('Greeting.repeatToStream should return observable of greetings ', () => { @@ -95,7 +95,7 @@ describe('Greeting suite', () => { .api(GreetingService) .create(); - expect.assertions(1); + expect.assertions(1); greetingService.repeatToStream('hey', 'hello').subscribe().unsubscribe(); expect(window['repeatToStreamUnsubscribe']).toBe(true); });