Introduction
Scalecube is a toolkit for creating microservices based systems.
as part of the solution, Scalecube provides the follow modules:
all modules are pluggable in a microservice container and can be customized and replaced.
Installation
scalecube available in three templates:
package | default configuration |
---|---|
@scalecube/browser | provide default configuration for running in browser |
@scalecube/node | provide default configuration for running in server |
@scalecube/scalecube-microservice | does not provide any default configuration |
package | yarn | npm |
---|---|---|
@scalecube/browser | yarn add @scalecube/browser |
npm i @scalecube/browser |
@scalecube/node | yarn add @scalecube/node |
npm i @scalecube/node |
@scalecube/scalecube-microservice | yarn add @scalecube/scalecube-microservice |
npm i @scalecube/scalecube-microservice |
Motivation
Scalecube provide solution for microservice's architecture.
It is based on the principle of Decouple by interface.
it is event-base system that allow to create loosely coupled services in a distributed environment.
Environment
scalecube can be used on browser or node
Reactive programing.
support Observable pattern.
Isolation
RunTime
Different services communicate via events, this solution isolates each service.
if one of the services throw exception, it won't break the whole js application.
Development
Each feature/service can be developed in isolation from other features/services.
services will be able to integrate together base on the interface of each service.
private methods/property
side effect of using Scalecube allow you to design a system in which the developer of the service can determine which methods/property are public.
only methods/property that are in the service definition can be access from out-side the service.
Scalability
RunTime
Easy to bootstrap in every environment/process.
Browser
A feature can be located on the main thread or in a web-worker,
Scalecube will manage the communication between the services.
Allow you to split your services between multiple process and scale your runtime processing.
NodeJS
A feature can be located on different servers.
Scalecube will manage the communication between the services.
Development
Scalecube provide easy way to integrate services base on their definition.
Old browser support
currently @scalecube/browser
transpile the code to es5.
but it is still require to add proxy-polyfill to browsers that does not have proxy support.
browser | version |
---|---|
Chrome | 37+ |
IE | 11 |
Edge | 15 |
FF | 41 |
Safari | 7.1 |
Core-concepts
Member
member is an entity in the distributed environment.
in the eco-system of scalecube, member will be a microservice container.
Distributed environment
Distributed environment is collection of members that share services between them.
Each member have access to all the services that are shared in the distributed environment.
possible topologies:
- Star - when all microservice container are connected to the same microservice seed.
- Hybrid - most of the microservices instance act as seed.
Registry
Registry store all endpoints of the available services it can request.
the registry reflect the state in the distributed environment.
if the state has changed, then the registry is notified and update accordingly.
ServiceCall
ServiceCall is the process of requesting a service to execute.
Scenario: microservice use its own service (LocalCall)
Given a service (definition + reference)
And bootstraping a microservice container with the service
When using the service definition to create a proxy from the microservice container
And calling a method from the service
Then the microservice container will perform localCall inorder to execute the method
Scenario: microservice use other microservice service (RemoteCall)
Given a service (definition + reference)
And bootstraping a microservice container A with the service
And bootstraping a microservice container B without the service
When using the service definition to create a proxy from the microservice container B
And calling a method from the service
Then the microservice container B will perform remoteCall to microservice container A inorder to request excution of the method
And the microservice container A will perform localCall inorder to execute the method
// main.js
import { createMicroservice } from '@scalecube/scalecube-microservice';
const msA = createMicroservice({ address: 'msA', services:[{ /* add your services */ }]});
const msB = createMicroservice({ address: 'msB', seedAddress : 'msA', services:[{ /* add your services */ }]});
const proxyA = msA.createProxy({ /* create proxy to the services on the microservice instance */ });
const proxyB = msB.createProxy({ /* create proxy to the services on the other microservice instance */ });
LocalCall
When a microservice use its own services.
RemoteCall
When a microservice use another microservice's services.
Seed
the seed is a microservice container that used as an entry-point to the distributed environment. each microservice can act as a seed for other microservice containers.
seedAddress is the address of the seed.
API
Address
interface Address {
host: string;
port: number;
protocol: string;
path: string;
}
Address is the URI for the service.
- host - unique identifier that allows other computers to access it.
- port - determine on which port number the server will receive the data.
- protocol - rules for communication between server and client (ws | pm | tcp)
- path - relative address.
AsyncModel
type RequestStreamAsyncModel = 'requestStream';
type RequestResponseAsyncModel = 'requestResponse';
type AsyncModel = RequestStreamAsyncModel | RequestResponseAsyncModel;
AsyncModel is the way a service can be resolved.
It can be a stream and use requestStream
or can be a promise and use requestResponse
- RequestStreamAsyncModel - Defines Stream asyncModel ( Observable, Flowable , etc.. ).
- RequestResponseAsyncModel - Defines Async asyncModel ( Promise ).
Cluster
type JoinCluster = (options: ClusterOptions) => Cluster;
interface ClusterOptions {
address: Address;
seedAddress?: Address;
itemsToPublish: any;
retry?: {
timeout: number;
};
debug?: boolean;
}
interface Cluster {
getCurrentMembersData: () => Promise<MembersData>;
listen$: () => Observable<ClusterEvent>;
destroy: () => Promise<string>;
}
// browser:
import { joinCluster } from '@scalecube/cluster-browser';
// server:
import { joinCluster } from '@scalecube/cluster-nodejs';
const cluster = joinCluster({
address: { /* my address */ },
seedAddress: {/* address to the distributed environment */},
itemsToPublish: [/* items to publish in the distributed environment */]
});
cluster.listen$().subscribe((response)=>{console.log(response)});
create a member from the data it receive from the discovery,
and use it in-order to share data in the distributed environment.
scalecube provide two cluster implementations:
* @scalecube/cluster-browser
* @scalecube/cluster-nodejs
- address - address of the member
- seedAddress - address of the member that act as the seed
- itemsToPublish - item to share with the different members
- retry - retry configuration for connecting members
debug - debug flag
getCurrentMembersData - resolve with the current information of the other members in the distributed environment
listen$ - subscribe to changes in the members state
destroy - resolve when cluster is destroyed
Discovery
type CreateDiscovery = (options: DiscoveryOptions) => Discovery;
interface DiscoveryOptions {
address: Address;
itemsToPublish: Item[];
seedAddress?: Address;
cluster?: (opt: ClusterOptions) => Cluster;
debug?: boolean;
}
interface Discovery {
discoveredItems$: () => Observable<ServiceDiscoveryEvent>;
destroy(): Promise<string>;
}
type Item = any;
Discovery is a tool that connect the microservice instance to the distributed environment.
It convert events received from the distributed environment to events that the registry can understand.
- address - A unique address.
- itemsToPublish - The data that the discovery need to share.
- seedAddress - the address we want to use in-order to connect to the distributed environment.
- cluster - optional pluggable cluster
debug - discovery logs
discoveredItems$ - An Observable sequence that describes all the items that published by other discoveries.
Emits new array of all items each time new discovery is created or destroyed.destroy - Destroy the discovery:
- Completes discoveredItems$.
- Notifies other discoveries that this discovery's items are not available anymore.
- Resolves with the message, that specifies the address of the discovery.
- Completes discoveredItems$.
Endpoint
interface Endpoint {
qualifier: string;
serviceName: string;
methodName: string;
asyncModel: AsyncModel;
address: Address;
}
Endpoint is the metadata of a service.
Contain information of how to access the service.
- qualifier - The combination of serviceName and methodName:
- serviceName - The name of a service, that is provided in serviceDefinition.
- methodName - The name of a method, that is provided in the methods map in serviceDefinition.
- asyncModel - Type of communication between a consumer and a provider.
- address - A unique address of an endpoint URI format:
:// : /
LookUp
type LookUp = (options: LookupOptions) => Endpoint[] | [];
interface LookupOptions {
qualifier: string;
}
Search for endPoints in the registry that match the qualifier.
- qualifier - The combination of serviceName and methodName:
Message
interface Message {
qualifier: string;
data: any[];
}
const message = {
qualifier : 'Service/someMethod',
data: ['value']
}
structure of the data in scalecube.
- qualifier - The combination of serviceName and methodName:
- data - Arguments of the invoked function.
Microservice
type CreateMicroservice = (options: MicroserviceOptions) => Microservice;
export interface Microservice {
destroy: () => Promise<any>;
createProxy: CreateProxy;
createServiceCall: CreateServiceCall;
}
export interface MicroserviceOptions {
defaultRouter?: Router;
services?: Service[];
seedAddress?: Address | string;
address?: Address | string;
transport?: Transport;
cluster?: (opt: ClusterOptions) => Cluster;
debug?: boolean;
}
import { createMicroservice } from '@scalecube/scalecube-microservice';
import { TransportNodeJS } from '@scalecube/transport-nodejs';
import { joinCluster } from '@scalecube/cluster-nodejs';
const microserviceInstance = createMicroservice({
services: [/* array of services */],
seedAddress : 'pm://myOrganization:8080/ServiceA',
address : {
protocol : 'pm',
host: 'myOrganization',
port : 8080,
path: 'ServiceB'
},
transport: TransportNodeJS, // scalecube provide a default transport configuration when running on browser,
cluster: joinCluster, // scalecube provide a default cluster configuration when running on browser,
defaultRouter: retryRouter({period:10}),
debug: true // default is false
})
- destroy - The method is used to delete a microservice and close all the subscriptions related with it.
- createProxy - Creates a proxy to a method and provides extra logic when is invoked.
createServiceCall - Exposes serviceCall to a user (not via Proxy)
defaultRouter - set a default router for this microservice container
services - An array of services, that will exist inside a microservice container
seedAddress - The seedAddress is an address or a string (URI format) of another microservice container in our distributed env.
address - An address or a string (URI format) for this microservice instance, other microservices can use this address to connect with this microservice container.
transport - a module that implements MicroserviceTransport.
cluster - a module that implements Cluster API
debug - add logs
Router
import { roundRobin, retryRouter } from '@scalecube/routers';
const proxyA = ms.createProxy({serviceDefinition, router: roundRobin});
const proxyB = ms.createProxy({serviceDefinition, router: retryRouter({period: 10})});
type Router = (options: RouterOptions) => Promise<Endpoint>;
interface RouterOptions {
lookUp: LookUp;
message: Message;
}
type RetryRouter = (options: RetryRouterOptions) => Router
interface RetryRouterOptions {
period: number;
maxRetry?: number
}
router is a tool for picking the best service base on given criteria.
- lookUp - The function that finds Endpoint by given criteria.
- message - metadata, contain criteria for picking the Endpoint
default
pick the first available item.
RoundRobin
pick the next item from a list of available items.
retryRouter
ping the registry every @ms and checking if there are any available items. pick the first available item.
Service
interface Service {
definition: ServiceDefinition;
reference: ServiceReference;
}
interface ServiceDefinition {
serviceName: string;
methods: {
[methodName: string]: {
asyncModel: AsyncModel;
};
};
}
type ServiceReference = ServiceFactory | ServiceObject;
type ServiceFactory = ({ createProxy, createServiceCall }: ServiceFactoryOptions) => ServiceObject;
interface ServiceObject {
constructor?: any;
[methodName: string]: any;
}
interface ServiceFactoryOptions {
createProxy: CreateProxy;
createServiceCall: CreateServiceCall;
}
Service is combination of definition and the reference that uphold the contract.
- definition - metadata that define the service.
- reference - code of the service
ServiceDefinition
Its the metadata that describe the service.
- serviceName - The name of a service
- methods - Map of methods that exist in the service.
each method describe its asyncModel.
ServiceReference
Its the code of the service.
- ServiceFactory - callback that provide life-cycle/inject hook in the bootstrap process.
- ServiceObject - object that contains the functionality described in the serviceDefinition.
Transport
interface Transport {
clientTransport: ClientTransport;
serverTransport: ServerTransport;
}
interface ClientTransport {
start: (options: ClientTransportOptions) => Promise<RequestHandler>;
destroy: TDestroy;
}
type ServerTransport = (options: ServerTransportOptions) => ServerStop;
interface ClientTransportOptions {
remoteAddress: Address;
logger: TLogger;
}
interface ServerTransportOptions {
localAddress: Address;
serviceCall: RequestHandler;
logger: TLogger;
}
interface RequestHandler {
requestResponse: (message: Message) => Promise<any>;
requestStream: (message: Message) => Observable<any>;
}
type ServerStop = () => void;
type TLogger = (msg: any, type: 'warn' | 'log') => void;
type TDestroy = ({ logger }: TDestroyOptions) => void;
interface TDestroyOptions {
address: string;
logger: TLogger;
}
Opinionated communication layer.
It is used when requesting a service from another microservice instance.
When bootstrapping microservice, it is possible to pass transport in the options.
transport is your custom implementation to RSocket Transport Providers.
- clientProvider - implementation for the client side.
- start - open connection to remote container and resolve with RequestHandler to call the remote container
destroy - remove all open connections of the container
serverProvider - implementation for the server side.
ServerStop - remove all open connections of this container
Bootstrap
bootstrap the microservice can be done in 3 steps:
1. define the service
interface ServiceDefinition {
serviceName: string;
methods: {
[methodName: string]: {
asyncModel: AsyncModel;
};
};
}
import { ASYNC_MODEL_TYPES } from '@scalecube/scalecube-microservice';
const serviceDefinition = {
serviceName: 'Service',
methods:{
someMethod : {
asyncModel : ASYNC_MODEL_TYPES.RequestResponse
}
}
}
service definition is the contract between the provider to the consumer of the service.
in other words, it is the contract that the service must uphold.
service definition is used when we are bootstrapping a service and when we are creating a proxy to a service.
when we are boostraping the service we are binding the serviceReference with the serviceDefinition. when we are creating a proxy with a serviceDefinition then scalecube search for the serviceReference that is bound to the serviceDefinition.
2. create the serviceReference
// class example
class Service {
constructor(){
}
someMethod(){
return Promise.resolve('some method been resolved');
}
}
// module example
const someMethod = () => Promise.resolve('some method been resolved');
type ServiceReference = ServiceFactory | ServiceObject;
type ServiceFactory = ({ createProxy, createServiceCall }: ServiceFactoryOptions) => ServiceObject;
interface ServiceObject {
constructor?: any;
[methodName: string]: any;
}
interface ServiceFactoryOptions {
createProxy: CreateProxy;
createServiceCall: CreateServiceCall;
}
ServiceReference is the implementation of the contract.
It can be a class instance, module or a callback function.
passing callback function in the ServiceReference call depedency hook and it can be used to inject proxy/service call to the service.
it is possible that the service will contain more functionality then what you define in the contract,
but only the functions that are in the definition will be public (accessible) in the distributed environment.
3. creating microservice
import { createMicroservice } from '@scalecube/scalecube-microservice';
const ms = createMicroservice({
services : [{
reference : {someMethod},
definition: serviceDefinition
},
{
reference : new Service(),
definition: serviceDefinition
}]
});
type CreateMicroservice = (options: MicroserviceOptions) => Microservice;
interface MicroserviceOptions {
services?: Service[];
seedAddress?: Address | string;
address?: Address | string;
transport?: Transport;
cluster?: (opt: ClusterOptions) => Cluster;
debug?: boolean;
}
interface Service {
definition: ServiceDefinition;
reference: ServiceReference;
}
After creating a service and a service-definition we can now bootstrap our microservice.
- services - An array of services, that will exist inside a microservice container.
- seedAddress - seedAddress is the entry point to our distributed env.
- address - An address for this microservice instance.
- transport - optional pluggable transport.
- cluster - optional pluggable cluster.
- debug - optional logs.
Basic usage
After bootstrapping the microservice, we can use it to request services from the distributed environment
createProxy
type CreateProxy = <T = any>(options: ProxyOptions) => T;
interface ProxyOptions {
router?: Router;
serviceDefinition: ServiceDefinition;
}
const serviceProxy = ms.createProxy({serviceDefinition});
serviceProxy.someMethod().then(console.log) // resolve with `someMethod` response
It is possible to createProxy from the microservice instance we have just created.
This is a proxy to a different service that is shared in the distributed environment.
- router - Custom router specifies the logic of choosing the appropriate remoteService.
- serviceDefinition - The metadata for a service container, that includes the name of a service and the map of methods that are included in it.
createServiceCall
type CreateServiceCall = (options: CreateServiceCallOptions) => ServiceCall;
interface CreateServiceCallOptions {
router?: Router;
}
interface ServiceCall {
requestStream: (message: Message) => Observable<Message>;
requestResponse: (message: Message) => Promise<Message>;
}
const message = {
qualifier: 'Service/someMethod',
data: ['value']
};
ms.createServiceCall().requestResponse(message).then(console.log);
ms.createServiceCall().requestStream(message).subscribe(console.log);
serviceCall is another way to request a service.
it is more low level approach and the user must define the message
properly in-order for it to work.
good example for preferring serviceCall over Proxy is in the Gateway
,
in the Gateway we want to receive a request from outside of our distributed environment and then pass the request to the correct service inside ot it.
- router - Custom router specifies the logic of choosing the appropriate remoteService
- requestStream - A method using which a consumer requires a stream and receives an Observable sequence describing updates of the method and qualifier that was used for the invocation
- requestResponse - A method using which a consumer requires data and a provider responds with the data once in the form of promise,
that includes the response from the method and qualifier that was used for the invocation.
destroy
interface Microservice {
destroy: () => Promise<any>;
}
ms.destroy().then(console.log);
destroy the microservice instance.
- stop listen to the address.
- notify in the distributed environment that the services from this microservice are not available anymore.
- remove it self from the distributed environment.
- destroy - The method is used to delete a microservice and close all the subscriptions related with it.
Advance usage
remoteCall
createMicroservice({
services: [{
definition: serviceDefinition,
reference : new Service()
}],
address: 'A'
});
const localMs = createMicroservice({
seedAddress: 'A'
});
const proxyA = localMs.createProxy({serviceDefinition});
proxyA.someMethod().then(console.log);
remoteCall is a request for a service that located in different microservice container in our distributed environment,
the other microservice can be located on a different process and it will still be accessible with scalecube.
dependency injection
type ServiceFactory = ({ createProxy, createServiceCall }: ServiceFactoryOptions) => ServiceObject;
interface ServiceFactoryOptions {
createProxy: CreateProxy;
createServiceCall: CreateServiceCall;
}
interface ServiceObject {
constructor?: any;
[methodName: string]: any;
}
import { createMicroservice, ASYNC_MODEL_TYPES } from '@scalecube/scalecube-microservice';
const definitionA = {
serviceName: 'serviceA',
methods: {
someMethodA: {
asyncModel: ASYNC_MODEL_TYPES.REQUEST_RESPONSE,
},
},
};
const definitionB = {
serviceName: 'serviceB',
methods: {
someMethodB: {
asyncModel: ASYNC_MODEL_TYPES.REQUEST_RESPONSE,
},
},
};
class ServiceB {
constructor(proxyA) {
// work with proxy to serviceA
proxyA.someMethodA().then(console.log);
}
}
createMicroservice({
services: [
{
definition: definitionA,
reference : { someMethodA}
},
{
definition: definitionB,
reference: ({ createProxy, createServiceCall }) => {
const proxyA = createProxy({serviceDefinition: definitionA });
return new ServiceB(proxyA);
}
}
]
})
dependency hook is used if your service deepened on another service,
or if you want to add life cycle to your bootstrap process.
injectProxy example:
In the example we have two services with dependency between them,
ServiceB deepened on ServiceA.
instead of passing the class instance of serviceB in the reference, we are passing a callback.
the callback is called from scalecube as part of the bootstrapping process.
the callback will be called with createProxy or createServiceCall methods which allow us to create proxy to serviceA and inject it to ServiceB constructor.
this technique can be apply to modules by passing the proxy to a factory.
gateway
type RequestHandler = (serviceCall: ServiceCall, data: any, subscriber: any) => void;
interface GatewayOptions {
port: number;
requestResponse?: RequestHandler;
requestStream?: RequestHandler;
}
interface GatewayStartOptions {
serviceCall: ServiceCall;
}
interface Gateway {
start: (options: GatewayStartOptions) => void;
stop: () => void;
}
import {Gateway} from '@scalecube/rsocket-ws-gateway';
import {createMicroservice} from '@scalecube/scalecube-microservice';
const gateway = new Gateway({port : 3000});
const serviceCall = createMicroservice({
services: [{
reference: new Service(),
definition: serviceDefinition
}]
}).createServiceCall({});
gateway.start({serviceCall});
Its a technique to centralize all the requests that are coming from outside of the distributed environment.
scalecube provide gateway implementation base on RSocketWebsocket.
- port - The gateway will listen to it.
- requestResponse - handle requestResponse requests.
requestStream - handle requestStream requests.
serviceCall - low level approach for requesting a service in the distributed environment.
start - start the gateway.
stop - stop the gateway.
Web workers (browser)
Scalecube provide an easy way to work in the browser different process (aka webworkers)
it provide a workers tool to attach webworkers to scalecube ecosystem.
can be import from sclecube/browser
or scalecube/utils
.
- initialize - initialize the web-worker util.
- addWorker - add a web-worker to sclaecube's ecosystem.
- removeWorker - remove a web-worker from sclaecube's ecosystem.
Debug
Mocks
import utils = require('@scalecube/utils');
// polyfill for messageChannel
utils.mockMessageChannel();
When trying to test app as if running on browser and testing microservices in node environment (jest) and the test involve multiple microservice instances and performing remoteCall then it is require to add the code snippet before the test is running.
the snippet will mock scalecube check if running in node and will add polyfill messageChannel which required by browser implementation of scalecube.
Errors
Error Code | Message | Possible solution |
---|---|---|
MS0000 | microservice does not exists | microservice instance have been destroyed |
MS0001 | Message has not been provided | calling requestResponse or requestStream must contain a Message |
MS0002 | Message data has not been provided | Message must contain data property |
MS0003 | Message qualifier has not been provided | Message must contain qualifier property |
MS0004 | Message should not to be empty object | can not pass empty object as Message |
MS0005 | qualifier expected to be service/method format | qualifier is not a string divided by '/' |
MS0006 | Service missing definition | when bootstrap microservice you provide service without a contract |
MS0007 | Message format error: data must be Array | Message data property must be array, how can i pass array in message |
MS0008 | Not valid format, services must be Array | when bootstrap microservice, services must be array of service |
MS0009 | Not valid format, service must be Object | service must be an object |
MS0010 | Not valid format, Microservice configuration must be an Object | missing configuration when bootstrapping a microservice instance |
MS0011 | qualifier should not be empty string | qualifier must be valid string in the format 'part1/part2' |
MS0013 | Transport provider is not define | when running on nodejs, Transport must be provided |
MS0014 | service method |
try to call a method from a proxy that does not in the definition |
MS0015 | can't find services that match the give criteria: <qualifier> | requesting a service that is not in the registry |
MS0016 | <asyncModel does not match, expect asyncModel in the proxy definition>, but received |
asyncModel in the request does not match the asyncModel define in the registry for the service |
MS0017 | service (<qualifier>) has valid definition but reference is not a function. | ServiceObject method is not a function |
MS0018 | service does not uphold the contract, |
definition has a method that is not provided in the reference |
MS0019 | Not valid format, |
ServiceReference must return object |
MS0020 | Invalid format, definition must contain valid serviceName | serviceDefinition must contain property serviceName |
MS0021 | Invalid format, definition must contain valid methods of type object | methods must be of type object |
MS0022 | Invalid format, definition must contain valid methods | methods must be none empty object |
MS0023 | Invalid format, serviceName must be not empty string but received type |
fix the serviceDefinition, serviceName must be a string |
MS0024 | ROUTER_NOT_PROVIDED | pass router plugin in the createProxy |
MS0025 | (service provider)'s service 'serviceName/methodName' define as Promise but service return not Promise | incorrect implementation of the service |
MS0026 | (service provider)'s service 'serviceName/methodName' define as Observable but service return not Observable | incorrect implementation of the service |
MS0027 | (service provider)'s 'serviceName/methodName' has no valid response, expect Promise or Observable | incorrect implementation of the service |
MS0028 | invalid async model | asyncModel in definition is invalid |
Release Notes
0.1.5
0.1.4
0.1.4-next.19
0.1.4-next.18
0.1.4-next.17
0.1.4-next.15
0.1.4-next.14
0.1.4-next.13
0.1.4-next.12
0.1.4-next.11
0.1.4-next.10
0.1.4-next.9
0.1.4-next.8
0.1.4-next.7
FAQ
How can I pass array in message?
const arrayToPassInArgs = [1,2,3,4];
const valueToPassInArgs = 5;
const objectToPassInArgs = {'6':6};
const message = {
qualifier : 'Service/someMethod',
data: [arrayToPassInArgs, valueToPassInArgs, objectToPassInArgs]
}
It is possbile to pass any data structure in the message.
just need to make sure it wrap in array.
please look at the example
related topics:
Invoking a method from proxy throw error code MS0015 - can't find services ...
createProxy does not guarantee that the service is available.
it just provide a proxy to the service.
possible solutions:
using retryRouter when creating the proxy. retryRouter will ping the registry before the remoteCall till the service is registered.
related topics:
Does the order of services is important when using the dependency hook?
The order of the services you provide is the order in which they are registered in the registry.
but, you don't need the service in the registry in order to create a proxy to it.
farther more, it is possible to use the dependency hook for services that are located in other microservice instances.
possible solution:
it is common to apply retry logic in order to make sure the service will run.
related topics:
Does seedAddress and address are mandatory for scalecube?
No, they are both optional.
Why to provide seedAddress?
seedAddress is used to connected to a distributed environment.
you must provide the address to one of the microservice instance in the distributed environment you want to joined.
why to provide address?
It is important to set your microservice instance address if you want that other microservice instance will use it as seedAddress.
farther more, microservice without address won't be able to share it services in the distributed environment.
if no address is provided, then microservice bootstrap will generate address for you. auto generate address stop you from sharing your services in the distributed environment.
related topics:
remoteCall, distributed environment, seed, address
Does scalecube support in old browsers?
@scalecube/browser transpile to es5,
but you must add:
- babel-polyfill
- proxy-polyfill
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/proxy-polyfill@0.3.0/proxy.min.js"></script>