@weave-js/core 0.15.3 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +0 -0
- package/lib/broker/context.js +4 -11
- package/lib/broker/defaultOptions.js +3 -2
- package/lib/broker/index.js +80 -26
- package/lib/broker/public.d.ts +2 -1
- package/lib/buildRuntime.js +30 -13
- package/lib/cache/adapters/index.js +14 -0
- package/lib/cache/lock.js +17 -0
- package/lib/errorHandler.js +27 -2
- package/lib/errors.js +11 -1
- package/lib/helper/defineAction.js +22 -7
- package/lib/helper/defineBrokerOptions.js +26 -8
- package/lib/helper/defineService.js +29 -5
- package/lib/index.js +69 -19
- package/lib/logger/format/asHumanReadable.js +4 -4
- package/lib/metrics/common.js +1 -1
- package/lib/metrics/exporter/base.js +2 -2
- package/lib/metrics/exporter/event.js +15 -13
- package/lib/metrics/exporter/index.js +1 -1
- package/lib/metrics/index.js +28 -0
- package/lib/middlewares/bulkhead/index.js +3 -3
- package/lib/middlewares/cache/index.js +6 -5
- package/lib/middlewares/context-tracker/index.js +12 -5
- package/lib/middlewares/index.js +18 -0
- package/lib/middlewares/tracing/tags.js +2 -2
- package/lib/middlewares/validator/index.js +2 -2
- package/lib/registry/actionEndpoint.js +5 -5
- package/lib/registry/collections/actionCollection.js +2 -2
- package/lib/registry/collections/endpointCollection.js +5 -5
- package/lib/registry/collections/eventCollection.js +5 -5
- package/lib/registry/collections/nodeCollection.js +2 -2
- package/lib/registry/collections/serviceCollection.js +2 -2
- package/lib/registry/node.js +1 -1
- package/lib/registry/registry.js +24 -15
- package/lib/registry/service/parseAction.js +11 -2
- package/lib/registry/service/parseEvent.js +2 -1
- package/lib/registry/service/service.js +29 -8
- package/lib/registry/serviceItem.js +2 -2
- package/lib/runtime/initActionInvoker.js +5 -1
- package/lib/runtime/initCache.js +4 -0
- package/lib/runtime/initContextFactory.js +6 -15
- package/lib/runtime/initEventbus.js +25 -4
- package/lib/runtime/initLogger.js +30 -10
- package/lib/runtime/initMetrics.js +18 -8
- package/lib/runtime/initRegistry.js +1 -1
- package/lib/runtime/initServiceManager.js +4 -0
- package/lib/runtime/initTracing.js +5 -1
- package/lib/runtime/initTransport.js +1 -1
- package/lib/runtime/initUuidFactory.js +1 -5
- package/lib/runtime/initValidator.js +1 -6
- package/lib/tracing/collectors/base.js +21 -3
- package/lib/tracing/collectors/event.js +10 -0
- package/lib/tracing/collectors/index.js +34 -1
- package/lib/transport/adapters/adapterBase.js +14 -4
- package/lib/transport/adapters/fromURI.js +31 -23
- package/lib/transport/createTransport.js +30 -13
- package/lib/transport/messageHandlers.js +3 -3
- package/lib/utils/index.js +17 -1
- package/lib/utils/options.js +70 -2
- package/lib/utils/restoreError.js +25 -0
- package/lib/utils/wrap-handler.js +22 -0
- package/package.json +2 -1
- package/types/index.d.ts +958 -0
- /package/lib/{types.js → types.__js} +0 -0
package/lib/metrics/common.js
CHANGED
|
@@ -4,11 +4,11 @@ module.exports = (options) => {
|
|
|
4
4
|
const cache = {};
|
|
5
5
|
|
|
6
6
|
cache.init = (registry) => {
|
|
7
|
-
Promise.resolve(new WeaveError('Init method not implemented'));
|
|
7
|
+
return Promise.resolve(new WeaveError('Init method not implemented'));
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
cache.stop = (registry) => {
|
|
11
|
-
Promise.resolve(new WeaveError('Stop method not implemented'));
|
|
11
|
+
return Promise.resolve(new WeaveError('Stop method not implemented'));
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
return cache;
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
const
|
|
1
|
+
const BaseAdapter = require('./base');
|
|
2
2
|
|
|
3
3
|
module.exports = (options) => {
|
|
4
4
|
const lastChanges = new Set();
|
|
5
5
|
|
|
6
|
-
const adapter =
|
|
6
|
+
const adapter = BaseAdapter(options);
|
|
7
7
|
|
|
8
|
-
const sendEvent = (
|
|
9
|
-
const broker = registry.broker;
|
|
10
|
-
const list =
|
|
8
|
+
const sendEvent = () => {
|
|
9
|
+
const broker = adapter.registry.broker;
|
|
10
|
+
const list = adapter.registry.list();
|
|
11
11
|
|
|
12
|
-
broker.emit(
|
|
12
|
+
broker.emit(adapter.options.eventName, list);
|
|
13
13
|
|
|
14
14
|
lastChanges.clear();
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
adapter.init = (registry) => {
|
|
18
|
-
|
|
18
|
+
adapter.options = Object.assign({
|
|
19
19
|
eventName: '$metrics.changed',
|
|
20
20
|
interval: 5000
|
|
21
|
-
});
|
|
21
|
+
}, options);
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
adapter.registry = registry;
|
|
24
24
|
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (adapter.options.interval > 0) {
|
|
26
|
+
adapter.timer = setInterval(() => sendEvent(), adapter.options.interval);
|
|
27
|
+
adapter.timer.unref();
|
|
28
|
+
} else {
|
|
29
|
+
adapter.timer = undefined;
|
|
28
30
|
}
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
adapter.stop = () => {
|
|
32
|
-
clearInterval(
|
|
34
|
+
clearInterval(adapter.timer);
|
|
33
35
|
return Promise.resolve();
|
|
34
36
|
};
|
|
35
37
|
|
package/lib/metrics/index.js
CHANGED
|
@@ -1,2 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics collection and monitoring system
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized metrics collection for:
|
|
5
|
+
* - Request/response times and counts
|
|
6
|
+
* - Error rates and types
|
|
7
|
+
* - Node performance metrics
|
|
8
|
+
* - Custom application metrics
|
|
9
|
+
* - System resource utilization
|
|
10
|
+
*
|
|
11
|
+
* Supports multiple metric types:
|
|
12
|
+
* - Counters: Incrementing values (request counts, errors)
|
|
13
|
+
* - Gauges: Current values (memory usage, active connections)
|
|
14
|
+
* - Histograms: Value distributions (response times, payload sizes)
|
|
15
|
+
* - Info: Static metadata (version, build info)
|
|
16
|
+
*
|
|
17
|
+
* @namespace Metrics
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Metric constants and identifiers
|
|
22
|
+
* @type {object}
|
|
23
|
+
*/
|
|
1
24
|
exports.Constants = require('./constants');
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Metric exporter implementations for different backends
|
|
28
|
+
* @type {object}
|
|
29
|
+
*/
|
|
2
30
|
exports.Exporter = require('./exporter');
|
|
@@ -7,8 +7,8 @@ const { Constants } = require('../../metrics');
|
|
|
7
7
|
const { WeaveQueueSizeExceededError } = require('../../errors');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types').Runtime} Runtime
|
|
11
|
-
* @typedef {import('../../types').Middleware} Middleware
|
|
10
|
+
* @typedef {import('../../types.__js').Runtime} Runtime
|
|
11
|
+
* @typedef {import('../../types.__js').Middleware} Middleware
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -44,7 +44,7 @@ module.exports = (runtime) => {
|
|
|
44
44
|
});
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
return function
|
|
47
|
+
return function bulkheadMiddleware (context, serviceInjections) {
|
|
48
48
|
// Execute action immediately
|
|
49
49
|
if (currentlyInFlight < bulkheadOptions.concurrentCalls) {
|
|
50
50
|
currentlyInFlight++;
|
|
@@ -21,7 +21,7 @@ module.exports = (runtime) => {
|
|
|
21
21
|
return function cacheMiddleware (context, serviceInjections) {
|
|
22
22
|
// handle enabled function
|
|
23
23
|
if (isEnabledFunction) {
|
|
24
|
-
if (!action.cache.
|
|
24
|
+
if (!action.cache.condition.call(null, context)) {
|
|
25
25
|
// Enabled function returns "false". Cache is disabled.
|
|
26
26
|
return handler(context, serviceInjections);
|
|
27
27
|
}
|
|
@@ -75,11 +75,12 @@ module.exports = (runtime) => {
|
|
|
75
75
|
|
|
76
76
|
return handler(context).then((result) => {
|
|
77
77
|
// Cache the value
|
|
78
|
-
cache.set(cacheHashKey, result, action.cache.ttl).then(() => {
|
|
79
|
-
|
|
80
|
-
release();
|
|
78
|
+
return cache.set(cacheHashKey, result, action.cache.ttl).then(() => {
|
|
79
|
+
return result;
|
|
81
80
|
});
|
|
82
|
-
|
|
81
|
+
}).finally(() => {
|
|
82
|
+
// Always release the lock
|
|
83
|
+
release();
|
|
83
84
|
});
|
|
84
85
|
});
|
|
85
86
|
});
|
|
@@ -52,32 +52,39 @@ module.exports = (runtime) => {
|
|
|
52
52
|
return new Promise((resolve) => {
|
|
53
53
|
if (contextList.length === 0) {
|
|
54
54
|
resolve();
|
|
55
|
+
return;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
let isTimedOut = false;
|
|
58
59
|
const timeout = setTimeout(() => {
|
|
59
60
|
isTimedOut = true;
|
|
60
61
|
log.error(new WeaveGracefulStopTimeoutError(service));
|
|
61
|
-
contextList = [];
|
|
62
62
|
resolve();
|
|
63
63
|
}, shutdownTimeout);
|
|
64
64
|
|
|
65
65
|
let isFirstCheck = true;
|
|
66
|
+
let checkInterval;
|
|
67
|
+
|
|
66
68
|
const checkContexts = () => {
|
|
67
69
|
if (contextList.length === 0) {
|
|
68
70
|
clearTimeout(timeout);
|
|
71
|
+
if (checkInterval) {
|
|
72
|
+
clearInterval(checkInterval);
|
|
73
|
+
}
|
|
69
74
|
resolve();
|
|
70
75
|
} else {
|
|
71
76
|
if (isFirstCheck) {
|
|
72
77
|
log.info(`Waiting for ${contextList.length} open Contexts...`);
|
|
73
78
|
isFirstCheck = false;
|
|
74
79
|
}
|
|
75
|
-
|
|
76
|
-
if (!isTimedOut) {
|
|
77
|
-
setTimeout(checkContexts, 100);
|
|
78
|
-
}
|
|
79
80
|
}
|
|
80
81
|
};
|
|
82
|
+
|
|
83
|
+
// Use setInterval instead of recursive setTimeout to prevent stack overflow
|
|
84
|
+
if (!isTimedOut) {
|
|
85
|
+
checkInterval = setInterval(checkContexts, 100);
|
|
86
|
+
checkInterval.unref();
|
|
87
|
+
}
|
|
81
88
|
setImmediate(checkContexts);
|
|
82
89
|
});
|
|
83
90
|
};
|
package/lib/middlewares/index.js
CHANGED
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Built-in middleware implementations for cross-cutting concerns
|
|
9
|
+
*
|
|
10
|
+
* Middlewares provide reusable functionality that can be applied to actions and events:
|
|
11
|
+
* - ActionHooks: Before/after/error hooks for actions
|
|
12
|
+
* - Bulkhead: Concurrency limiting and isolation
|
|
13
|
+
* - Cache: Response caching and invalidation
|
|
14
|
+
* - CircuitBreaker: Circuit breaker pattern for fault tolerance
|
|
15
|
+
* - ErrorHandler: Centralized error processing
|
|
16
|
+
* - Metrics: Performance monitoring and collection
|
|
17
|
+
* - Tracing: Distributed tracing support
|
|
18
|
+
* - Retry: Automatic retry with backoff strategies
|
|
19
|
+
* - Timeout: Request timeout handling
|
|
20
|
+
* - ContextTracker: Context lifecycle tracking
|
|
21
|
+
* - Validator: Parameter validation middleware
|
|
22
|
+
*
|
|
23
|
+
* @namespace Middlewares
|
|
24
|
+
*/
|
|
7
25
|
module.exports = {
|
|
8
26
|
ActionHooks: require('./action-hooks'),
|
|
9
27
|
Bulkhead: require('./bulkhead'),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {import("../../types.
|
|
3
|
-
* @typedef {import("../../types.
|
|
2
|
+
* @typedef {import("../../types.__js").Context} Context
|
|
3
|
+
* @typedef {import("../../types.__js").TracingOptions} TracingOptions
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { isFunction, dotGet, isObject } = require('@weave-js/utils');
|
|
@@ -8,8 +8,8 @@ const { WeaveParameterValidationError } = require('../../errors');
|
|
|
8
8
|
const { capitalize } = require('@weave-js/utils');
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @typedef {import('../../types').Runtime} Runtime
|
|
12
|
-
* @typedef {import('../../types').Middleware} Middleware
|
|
11
|
+
* @typedef {import('../../types.__js').Runtime} Runtime
|
|
12
|
+
* @typedef {import('../../types.__js').Middleware} Middleware
|
|
13
13
|
**/
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {import("../types.
|
|
3
|
-
* @typedef {import("../types.
|
|
4
|
-
* @typedef {import("../types.
|
|
5
|
-
* @typedef {import("../types.
|
|
6
|
-
* @typedef {import("../types.
|
|
2
|
+
* @typedef {import("../types.__js").Runtime} Runtime
|
|
3
|
+
* @typedef {import("../types.__js").Endpoint} Endpoint
|
|
4
|
+
* @typedef {import("../types.__js").Node} Node
|
|
5
|
+
* @typedef {import("../types.__js").Service} Service
|
|
6
|
+
* @typedef {import("../types.__js").ServiceAction} ServiceAction
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/*
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types.
|
|
11
|
-
* @typedef {import('../../types.
|
|
10
|
+
* @typedef {import('../../types.__js').Registry} Registry
|
|
11
|
+
* @typedef {import('../../types.__js').ServiceActionCollection} ServiceActionCollection
|
|
12
12
|
*/
|
|
13
13
|
const { omit } = require('@weave-js/utils');
|
|
14
14
|
const { createEndpointList } = require('./endpointCollection');
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types.
|
|
11
|
-
* @typedef {import('../../types.
|
|
12
|
-
* @typedef {import('../../types.
|
|
13
|
-
* @typedef {import('../../types.
|
|
14
|
-
* @typedef {import('../../types.
|
|
10
|
+
* @typedef {import('../../types.__js').Runtime} Runtime
|
|
11
|
+
* @typedef {import('../../types.__js').EventCollection} EventCollection
|
|
12
|
+
* @typedef {import('../../types.__js').Service} Service
|
|
13
|
+
* @typedef {import('../../types.__js').Node} Node
|
|
14
|
+
* @typedef {import('../../types.__js').EndpointCollection} EndpointCollection
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
const { createActionEndpoint } = require('../actionEndpoint');
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types.
|
|
11
|
-
* @typedef {import('../../types.
|
|
12
|
-
* @typedef {import('../../types.
|
|
13
|
-
* @typedef {import('../../types.
|
|
14
|
-
* @typedef {import('../../types.
|
|
10
|
+
* @typedef {import('../../types.__js').Registry} Registry
|
|
11
|
+
* @typedef {import('../../types.__js').EventCollection} EventCollection
|
|
12
|
+
* @typedef {import('../../types.__js').Service} Service
|
|
13
|
+
* @typedef {import('../../types.__js').Node} Node
|
|
14
|
+
* @typedef {import('../../types.__js').EndpointCollection} EndpointCollection
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
const { omit, match } = require('@weave-js/utils');
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types.
|
|
11
|
-
* @typedef {import('../../types.
|
|
10
|
+
* @typedef {import('../../types.__js').Registry} Registry
|
|
11
|
+
* @typedef {import('../../types.__js').NodeCollection} NodeCollection
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
const { getIpList, omit } = require('@weave-js/utils');
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('../../types').Registry} Registry
|
|
11
|
-
* @typedef {import('../../types').ServiceCollection} ServiceCollection
|
|
10
|
+
* @typedef {import('../../types.__js').Registry} Registry
|
|
11
|
+
* @typedef {import('../../types.__js').ServiceCollection} ServiceCollection
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
// const { createEndpointCollection } = require('./endpoint-collection')
|
package/lib/registry/node.js
CHANGED
package/lib/registry/registry.js
CHANGED
|
@@ -6,17 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* @typedef {import('
|
|
10
|
-
* @typedef {import('
|
|
11
|
-
* @typedef {import('
|
|
12
|
-
* @typedef {import('
|
|
13
|
-
* @typedef {import('
|
|
14
|
-
* @typedef {import('
|
|
15
|
-
* @typedef {import('
|
|
16
|
-
|
|
17
|
-
* @typedef {import('../types.js').MiddlewareHandler} MiddlewareHandler
|
|
18
|
-
* @typedef {import('../types.js').ServiceChangedDelegate} ServiceChangedDelegate
|
|
19
|
-
*/
|
|
9
|
+
* @typedef {import('../../types').Registry} Registry
|
|
10
|
+
* @typedef {import('../../types').Runtime} Runtime
|
|
11
|
+
* @typedef {import('../../types').Broker} Broker
|
|
12
|
+
* @typedef {import('../../types').Node} Node
|
|
13
|
+
* @typedef {import('../../types').ServiceItem} ServiceItem
|
|
14
|
+
* @typedef {import('../../types').Endpoint} Endpoint
|
|
15
|
+
* @typedef {import('../../types').MiddlewareHandler} MiddlewareHandler
|
|
16
|
+
*/
|
|
20
17
|
|
|
21
18
|
const { safeCopy } = require('@weave-js/utils');
|
|
22
19
|
|
|
@@ -32,10 +29,22 @@ const { WeaveServiceNotFoundError, WeaveServiceNotAvailableError } = require('..
|
|
|
32
29
|
const noop = () => {};
|
|
33
30
|
|
|
34
31
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
|
|
32
|
+
* Creates a service registry for managing distributed services and nodes
|
|
33
|
+
*
|
|
34
|
+
* The registry is responsible for:
|
|
35
|
+
* - Tracking available nodes and their services
|
|
36
|
+
* - Load balancing requests across service instances
|
|
37
|
+
* - Service discovery and routing
|
|
38
|
+
* - Handling node lifecycle events (connect/disconnect)
|
|
39
|
+
* - Managing action and event endpoints
|
|
40
|
+
*
|
|
41
|
+
* @param {Runtime} runtime - Weave runtime instance
|
|
42
|
+
* @returns {Registry} Initialized registry instance with collections and routing logic
|
|
43
|
+
* @example
|
|
44
|
+
* const registry = createRegistry(runtime);
|
|
45
|
+
* registry.registerLocalService(serviceItem);
|
|
46
|
+
* const endpoint = registry.getNextAvailableActionEndpoint('math.add');
|
|
47
|
+
*/
|
|
39
48
|
exports.createRegistry = (runtime) => {
|
|
40
49
|
const { middlewareHandler } = runtime;
|
|
41
50
|
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
const { isFunction, clone,
|
|
1
|
+
const { isFunction, clone, isObject, promisify } = require('@weave-js/utils');
|
|
2
2
|
const { WeaveError } = require('../../errors');
|
|
3
|
-
|
|
3
|
+
const { wrapHandler } = require('../../utils/wrap-handler');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {import('../../../types').Runtime} runtime Runtime
|
|
8
|
+
* @param {import('../../../types').Service} service Service
|
|
9
|
+
* @param {import('../../../types').ServiceActionSchema} actionDefinition Action definition
|
|
10
|
+
* @param {string} name
|
|
11
|
+
* @returns {import('../../../types').ServiceActionDefinition}
|
|
12
|
+
*/
|
|
4
13
|
module.exports.parseAction = (runtime, service, actionDefinition, name) => {
|
|
5
14
|
let action = actionDefinition;
|
|
6
15
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const { isFunction, clone,
|
|
1
|
+
const { isFunction, clone, isObject, promisify } = require('@weave-js/utils');
|
|
2
|
+
const { wrapHandler } = require('../../utils/wrap-handler');
|
|
2
3
|
const { WeaveError } = require('../../errors');
|
|
3
4
|
|
|
4
5
|
module.exports.parseEvent = (runtime, service, eventDefinition, name) => {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {import("
|
|
3
|
-
* @typedef {import("
|
|
4
|
-
* @typedef {import("
|
|
5
|
-
|
|
2
|
+
* @typedef {import("../../../types").Runtime} Runtime
|
|
3
|
+
* @typedef {import("../../../types").ServiceSchema} ServiceSchema
|
|
4
|
+
* @typedef {import("../../../types").Service} Service
|
|
5
|
+
* @typedef {import("../../../types").Context} Context
|
|
6
|
+
*/
|
|
6
7
|
|
|
7
8
|
const { isFunction, clone, isObject, promisify } = require('@weave-js/utils');
|
|
8
9
|
const { WeaveError } = require('../../errors');
|
|
@@ -11,10 +12,30 @@ const { parseEvent } = require('./parseEvent');
|
|
|
11
12
|
const { reduceMixins } = require('./reduceMixins');
|
|
12
13
|
const { createEventEndpoint } = require('../eventEndpoint');
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Creates a service instance from a service schema definition
|
|
16
|
+
*
|
|
17
|
+
* This factory function handles the complete service lifecycle:
|
|
18
|
+
* - Applies mixins and merges schemas
|
|
19
|
+
* - Parses and validates actions and events
|
|
20
|
+
* - Sets up service methods and lifecycle hooks
|
|
21
|
+
* - Initializes service metadata and settings
|
|
22
|
+
* - Creates action and event endpoints for the registry
|
|
23
|
+
*
|
|
24
|
+
* @param {Runtime} runtime - Weave runtime instance with broker reference
|
|
25
|
+
* @param {ServiceSchema} schema - Service definition containing actions, events, and configuration
|
|
26
|
+
* @returns {Service} Fully initialized service instance ready for registration
|
|
27
|
+
* @throws {WeaveError} When schema is missing or invalid
|
|
28
|
+
* @example
|
|
29
|
+
* const service = createServiceFromSchema(runtime, {
|
|
30
|
+
* name: 'math',
|
|
31
|
+
* version: '1.0.0',
|
|
32
|
+
* actions: {
|
|
33
|
+
* add: {
|
|
34
|
+
* params: { a: 'number', b: 'number' },
|
|
35
|
+
* handler: (ctx) => ctx.data.a + ctx.data.b
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* });
|
|
18
39
|
*/
|
|
19
40
|
exports.createServiceFromSchema = (runtime, schema) => {
|
|
20
41
|
// Check if a schema is given
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
const errors = require('../errors');
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Attach action invoker
|
|
5
|
+
* @param {Partial<import('../../types').Runtime>} runtime Runtime
|
|
6
|
+
*/
|
|
3
7
|
exports.initActionInvoker = (runtime) => {
|
|
4
8
|
const { registry, contextFactory, log, handleError } = runtime;
|
|
5
9
|
|
|
@@ -11,7 +15,7 @@ exports.initActionInvoker = (runtime) => {
|
|
|
11
15
|
* @returns {Promise} Promise
|
|
12
16
|
*/
|
|
13
17
|
const call = (actionName, data, opts = {}) => {
|
|
14
|
-
const endpoint = registry
|
|
18
|
+
const endpoint = registry?.getNextAvailableActionEndpoint(actionName, opts);
|
|
15
19
|
|
|
16
20
|
if (endpoint instanceof Error) {
|
|
17
21
|
return Promise.reject(endpoint)
|
package/lib/runtime/initCache.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
const { isFunction } = require('@weave-js/utils');
|
|
2
2
|
const { WeaveError } = require('../errors');
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Init Cache
|
|
6
|
+
* @param {import('../../types').Runtime} runtime Runtime
|
|
7
|
+
*/
|
|
4
8
|
exports.initCache = (runtime) => {
|
|
5
9
|
if (runtime.options.cache && runtime.options.cache.enabled) {
|
|
6
10
|
if (!isFunction(runtime.options.cache.adapter)) {
|
|
@@ -7,36 +7,27 @@
|
|
|
7
7
|
|
|
8
8
|
const { createContext } = require('../broker/context');
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {import('../types').Runtime} Runtime
|
|
12
|
-
* @typedef {import('../types').Context} Context
|
|
13
|
-
* @typedef {import('../types').Endpoint} Endpoint
|
|
14
|
-
* @typedef {import('../types').ActionOptions} ActionOptions
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
10
|
/**
|
|
18
11
|
* Init context factory.
|
|
19
|
-
* @param {Runtime} runtime - Runtime reference
|
|
20
|
-
* @returns {void}
|
|
12
|
+
* @param {import('../../types').Runtime} runtime - Runtime reference
|
|
21
13
|
*/
|
|
22
14
|
exports.initContextFactory = (runtime) => {
|
|
23
15
|
Object.defineProperty(runtime, 'contextFactory', {
|
|
24
16
|
value: {
|
|
25
17
|
/**
|
|
26
18
|
* Creates a new context
|
|
27
|
-
* @param {Endpoint} endpoint - Endpoint
|
|
28
|
-
* @param {any} data - Data
|
|
29
|
-
* @param {ActionOptions} opts Options
|
|
30
|
-
* @returns {Context} Context
|
|
19
|
+
* @param {import('../../types').Endpoint} endpoint - Endpoint
|
|
20
|
+
* @param {Record<string, any>} data - Data
|
|
21
|
+
* @param {import('../../types').ActionOptions} opts Options
|
|
22
|
+
* @returns {import('../../types').Context} Context
|
|
31
23
|
*/
|
|
32
|
-
create (endpoint, data, opts) {
|
|
24
|
+
create (endpoint, data, opts = {}) {
|
|
33
25
|
const context = createContext(runtime);
|
|
34
26
|
|
|
35
27
|
if (endpoint) {
|
|
36
28
|
context.setEndpoint(endpoint);
|
|
37
29
|
}
|
|
38
30
|
|
|
39
|
-
opts = opts || {};
|
|
40
31
|
context.setData(data);
|
|
41
32
|
// context.timeout = opts.timeout || 0
|
|
42
33
|
context.retryCount = opts.retryCount;
|
|
@@ -8,7 +8,7 @@ exports.initEventbus = (runtime) => {
|
|
|
8
8
|
* @param {*} [options=null] - Groups
|
|
9
9
|
* @returns {Promise<any>} - Result
|
|
10
10
|
*/
|
|
11
|
-
const emit = (eventName, payload, options) => {
|
|
11
|
+
const emit = async (eventName, payload, options) => {
|
|
12
12
|
if (Array.isArray(options)) {
|
|
13
13
|
options = { groups: options };
|
|
14
14
|
} else if (options == null) {
|
|
@@ -59,7 +59,17 @@ exports.initEventbus = (runtime) => {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
// Use allSettled to ensure all events are attempted even if some fail
|
|
63
|
+
const results = await Promise.allSettled(promises);
|
|
64
|
+
|
|
65
|
+
const failures = results.filter(result => result.status === 'rejected');
|
|
66
|
+
if (failures.length > 0) {
|
|
67
|
+
failures.forEach(failure => {
|
|
68
|
+
runtime.log.warn(failure.reason, `Failed to emit event "${eventName}" to remote service`);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return results;
|
|
63
73
|
};
|
|
64
74
|
|
|
65
75
|
/**
|
|
@@ -94,7 +104,7 @@ exports.initEventbus = (runtime) => {
|
|
|
94
104
|
* @param {*} [options=null] Groups
|
|
95
105
|
* @returns {Promise<any>} Promise
|
|
96
106
|
*/
|
|
97
|
-
const broadcast = (eventName, payload, options) => {
|
|
107
|
+
const broadcast = async (eventName, payload, options) => {
|
|
98
108
|
if (Array.isArray(options)) {
|
|
99
109
|
options = { groups: options };
|
|
100
110
|
} else if (options == null) {
|
|
@@ -124,7 +134,18 @@ exports.initEventbus = (runtime) => {
|
|
|
124
134
|
}
|
|
125
135
|
|
|
126
136
|
promises.push(broadcastLocal(eventName, payload, options));
|
|
127
|
-
|
|
137
|
+
|
|
138
|
+
// Use allSettled to ensure all broadcasts are attempted even if some fail
|
|
139
|
+
const results = await Promise.allSettled(promises);
|
|
140
|
+
|
|
141
|
+
const failures = results.filter(result => result.status === 'rejected');
|
|
142
|
+
if (failures.length > 0) {
|
|
143
|
+
failures.forEach(failure => {
|
|
144
|
+
runtime.log.warn(failure.reason, `Failed to broadcast event "${eventName}" to remote service`);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return results;
|
|
128
149
|
};
|
|
129
150
|
|
|
130
151
|
Object.defineProperty(runtime, 'eventBus', {
|