moleculer
moleculer copied to clipboard
how to approach mutually exclusive dependencies
I'm having trouble finding a supported way to do mutually exclusive dependencies with Moleculer's built-in service dependency API.
For example, the snippet below has two implicit, unasserted, dependencies (v2.service and v1.service) -- it would be nice to have more confidence that at least one of those is available at runtime.
const things = await ctx.call(
'v2.service.getThings',
{ active: true },
{
fallbackResponse: () => {
return ctx.call('v1.service.getThings', { active: true });
},
}
);
I, without looking at the code/examples, tried a dependencies of ['service'] and [{ name: 'service' }] thinking Moleculer may do some sort of resolution to match the name... with no luck. From looking around, I believe support would require a Moleculer change.
Something like:
{
dependencies: [
{ or: ['v1.service', 'v2.service'] }
],
}
could facilitate some special logic in the block below for "one or the other" searches https://github.com/moleculerjs/moleculer/blob/b71bd71dc2375a72d32c25e2718b4b36a8b57f60/src/service-broker.js#L1022-L1027
It seems best for members of the or special case to support the full set of version keys (shorthand with/without version, object, etc.). Though, I believe that would require enriching the Registry#hasService API to do partial matches. Not really sure on that one.
Some questions:
- [ ] Are these assumptions correct or is there already a way to do this?
- [ ] If not, is there a particular path forward you think would be best?
You can't do that currently with dependencies. But the idea is good, but I suggest other solution than or: [] because I think there is no real use-case that somebody wants to wait for different services with or.
My suggestion is that version can be an array, like:
{
dependencies: [
{ name: "myService", version: [1, 2] }
],
}
Current workaround if you don't use the dependencies in the schema, instead use the waitForServices in started. E.g.
{
name: "otherService",
started() {
while (true) {
try {
await this.waitForServices("v1.myService", 1000);
break;
} catch(err) {
try {
await this.waitForServices("v2.myService", 1000);
break;
} catch(err) {
// Wait again
}
}
}
}
}