@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.
Files changed (64) hide show
  1. package/index.mjs +0 -0
  2. package/lib/broker/context.js +4 -11
  3. package/lib/broker/defaultOptions.js +3 -2
  4. package/lib/broker/index.js +80 -26
  5. package/lib/broker/public.d.ts +2 -1
  6. package/lib/buildRuntime.js +30 -13
  7. package/lib/cache/adapters/index.js +14 -0
  8. package/lib/cache/lock.js +17 -0
  9. package/lib/errorHandler.js +27 -2
  10. package/lib/errors.js +11 -1
  11. package/lib/helper/defineAction.js +22 -7
  12. package/lib/helper/defineBrokerOptions.js +26 -8
  13. package/lib/helper/defineService.js +29 -5
  14. package/lib/index.js +69 -19
  15. package/lib/logger/format/asHumanReadable.js +4 -4
  16. package/lib/metrics/common.js +1 -1
  17. package/lib/metrics/exporter/base.js +2 -2
  18. package/lib/metrics/exporter/event.js +15 -13
  19. package/lib/metrics/exporter/index.js +1 -1
  20. package/lib/metrics/index.js +28 -0
  21. package/lib/middlewares/bulkhead/index.js +3 -3
  22. package/lib/middlewares/cache/index.js +6 -5
  23. package/lib/middlewares/context-tracker/index.js +12 -5
  24. package/lib/middlewares/index.js +18 -0
  25. package/lib/middlewares/tracing/tags.js +2 -2
  26. package/lib/middlewares/validator/index.js +2 -2
  27. package/lib/registry/actionEndpoint.js +5 -5
  28. package/lib/registry/collections/actionCollection.js +2 -2
  29. package/lib/registry/collections/endpointCollection.js +5 -5
  30. package/lib/registry/collections/eventCollection.js +5 -5
  31. package/lib/registry/collections/nodeCollection.js +2 -2
  32. package/lib/registry/collections/serviceCollection.js +2 -2
  33. package/lib/registry/node.js +1 -1
  34. package/lib/registry/registry.js +24 -15
  35. package/lib/registry/service/parseAction.js +11 -2
  36. package/lib/registry/service/parseEvent.js +2 -1
  37. package/lib/registry/service/service.js +29 -8
  38. package/lib/registry/serviceItem.js +2 -2
  39. package/lib/runtime/initActionInvoker.js +5 -1
  40. package/lib/runtime/initCache.js +4 -0
  41. package/lib/runtime/initContextFactory.js +6 -15
  42. package/lib/runtime/initEventbus.js +25 -4
  43. package/lib/runtime/initLogger.js +30 -10
  44. package/lib/runtime/initMetrics.js +18 -8
  45. package/lib/runtime/initRegistry.js +1 -1
  46. package/lib/runtime/initServiceManager.js +4 -0
  47. package/lib/runtime/initTracing.js +5 -1
  48. package/lib/runtime/initTransport.js +1 -1
  49. package/lib/runtime/initUuidFactory.js +1 -5
  50. package/lib/runtime/initValidator.js +1 -6
  51. package/lib/tracing/collectors/base.js +21 -3
  52. package/lib/tracing/collectors/event.js +10 -0
  53. package/lib/tracing/collectors/index.js +34 -1
  54. package/lib/transport/adapters/adapterBase.js +14 -4
  55. package/lib/transport/adapters/fromURI.js +31 -23
  56. package/lib/transport/createTransport.js +30 -13
  57. package/lib/transport/messageHandlers.js +3 -3
  58. package/lib/utils/index.js +17 -1
  59. package/lib/utils/options.js +70 -2
  60. package/lib/utils/restoreError.js +25 -0
  61. package/lib/utils/wrap-handler.js +22 -0
  62. package/package.json +2 -1
  63. package/types/index.d.ts +958 -0
  64. /package/lib/{types.js → types.__js} +0 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @typedef {import('../types.js').Runtime} Runtime
2
+ * @typedef {import('../types.__js').Runtime} Runtime
3
3
  */
4
4
  const os = require('os');
5
5
  const Constants = require('./constants');
@@ -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 { createBaseMetricAdapter } = require('./base');
1
+ const BaseAdapter = require('./base');
2
2
 
3
3
  module.exports = (options) => {
4
4
  const lastChanges = new Set();
5
5
 
6
- const adapter = createBaseMetricAdapter(options);
6
+ const adapter = BaseAdapter(options);
7
7
 
8
- const sendEvent = (registry, options) => {
9
- const broker = registry.broker;
10
- const list = this.registry.list();
8
+ const sendEvent = () => {
9
+ const broker = adapter.registry.broker;
10
+ const list = adapter.registry.list();
11
11
 
12
- broker.emit(this.options.eventName, list);
12
+ broker.emit(adapter.options.eventName, list);
13
13
 
14
14
  lastChanges.clear();
15
15
  };
16
16
 
17
17
  adapter.init = (registry) => {
18
- this.options = Object.assign(options, {
18
+ adapter.options = Object.assign({
19
19
  eventName: '$metrics.changed',
20
20
  interval: 5000
21
- });
21
+ }, options);
22
22
 
23
- this.registry = registry;
23
+ adapter.registry = registry;
24
24
 
25
- if (this.options.interval > 0) {
26
- this.timer = setInterval(() => sendEvent(), this.options.interval);
27
- this.timer.unref();
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(this.timer);
34
+ clearInterval(adapter.timer);
33
35
  return Promise.resolve();
34
36
  };
35
37
 
@@ -24,7 +24,7 @@ module.exports = {
24
24
  let cacheFactory;
25
25
 
26
26
  if (options === true) {
27
- cacheFactory = this.adapters.Event;
27
+ cacheFactory = adapters.Event;
28
28
  } else if (isString(options)) {
29
29
  const cache = getByName(options);
30
30
 
@@ -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 bulkheadMiddlware (context, serviceInjections) {
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.enabled.call(null, context)) {
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
- // release the lock
80
- release();
78
+ return cache.set(cacheHashKey, result, action.cache.ttl).then(() => {
79
+ return result;
81
80
  });
82
- return result;
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
  };
@@ -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.js").Context} Context
3
- * @typedef {import("../../types.js").TracingOptions} TracingOptions
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.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
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.js').Registry} Registry
11
- * @typedef {import('../../types.js').ServiceActionCollection} ServiceActionCollection
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.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
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.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
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.js').Registry} Registry
11
- * @typedef {import('../../types.js').NodeCollection} NodeCollection
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')
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @typedef {import('../types.js').Node} Node
8
+ * @typedef {import('../types.__js').Node} Node
9
9
  */
10
10
 
11
11
  const { cpuUsage } = require('@weave-js/utils');
@@ -6,17 +6,14 @@
6
6
  */
7
7
 
8
8
  /**
9
- * @typedef {import('../types.js').Registry} Registry
10
- * @typedef {import('../types.js').NodeCollection} NodeCollection
11
- * @typedef {import('../types.js').ServiceCollection} ServiceCollection
12
- * @typedef {import('../types.js').ServiceActionCollection} ServiceActionCollection
13
- * @typedef {import('../types.js').EventCollection} EventCollection
14
- * @typedef {import('../types.js').Runtime} Runtime
15
- * @typedef {import('../types.js').Broker} Broker
16
- * @typedef {import('../types.js').Node} Node
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
- * Registry factory
36
- * @param {Runtime} runtime Runtime
37
- * @returns {Registry} Registry
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, wrapHandler, isObject, promisify } = require('@weave-js/utils');
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, wrapHandler, isObject, promisify } = require('@weave-js/utils');
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("../../types").Runtime} Runtime
3
- * @typedef {import("../../types").ServiceSchema} ServiceSchema
4
- * @typedef {import("../../types").Service} Service
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
- * Service factory
15
- * @param {Runtime} runtime Broker instance
16
- * @param {ServiceSchema} schema Service schema
17
- * @returns {Service} Service instance
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
@@ -6,8 +6,8 @@
6
6
  'use strict';
7
7
 
8
8
  /**
9
- * @typedef {import("../types").ServiceItem} ServiceItem
10
- * @typedef {import("../types").Node} Node
9
+ * @typedef {import("../types.__js").ServiceItem} ServiceItem
10
+ * @typedef {import("../types.__js").Node} Node
11
11
  */
12
12
 
13
13
  /**
@@ -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.getNextAvailableActionEndpoint(actionName, opts);
18
+ const endpoint = registry?.getNextAvailableActionEndpoint(actionName, opts);
15
19
 
16
20
  if (endpoint instanceof Error) {
17
21
  return Promise.reject(endpoint)
@@ -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
- return Promise.all(promises);
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
- return Promise.all(promises);
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', {