@magek/core 0.0.1
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/dist/authorizer.d.ts +7 -0
- package/dist/authorizer.js +35 -0
- package/dist/command-dispatcher.d.ts +8 -0
- package/dist/command-dispatcher.js +55 -0
- package/dist/core-concepts/data-migration/entities/data-migration-entity.d.ts +12 -0
- package/dist/core-concepts/data-migration/entities/data-migration-entity.js +37 -0
- package/dist/core-concepts/data-migration/events/data-migration-finished.d.ts +7 -0
- package/dist/core-concepts/data-migration/events/data-migration-finished.js +13 -0
- package/dist/core-concepts/data-migration/events/data-migration-started.d.ts +7 -0
- package/dist/core-concepts/data-migration/events/data-migration-started.js +13 -0
- package/dist/core-concepts/data-migration/events/entity-migrated.d.ts +9 -0
- package/dist/core-concepts/data-migration/events/entity-migrated.js +15 -0
- package/dist/core-concepts/touch-entity/events/entity-touched.d.ts +7 -0
- package/dist/core-concepts/touch-entity/events/entity-touched.js +13 -0
- package/dist/data-migrations.d.ts +8 -0
- package/dist/data-migrations.js +73 -0
- package/dist/decorators/command.d.ts +19 -0
- package/dist/decorators/command.js +47 -0
- package/dist/decorators/data-migration.d.ts +9 -0
- package/dist/decorators/data-migration.js +25 -0
- package/dist/decorators/entity.d.ts +32 -0
- package/dist/decorators/entity.js +100 -0
- package/dist/decorators/event-handler.d.ts +3 -0
- package/dist/decorators/event-handler.js +18 -0
- package/dist/decorators/event.d.ts +8 -0
- package/dist/decorators/event.js +22 -0
- package/dist/decorators/field-metadata-reader.d.ts +6 -0
- package/dist/decorators/field-metadata-reader.js +221 -0
- package/dist/decorators/global-error-handler.d.ts +2 -0
- package/dist/decorators/global-error-handler.js +15 -0
- package/dist/decorators/global-event-handler.d.ts +3 -0
- package/dist/decorators/global-event-handler.js +9 -0
- package/dist/decorators/health-sensor.d.ts +14 -0
- package/dist/decorators/health-sensor.js +38 -0
- package/dist/decorators/index.d.ts +16 -0
- package/dist/decorators/index.js +19 -0
- package/dist/decorators/metadata.d.ts +13 -0
- package/dist/decorators/metadata.js +55 -0
- package/dist/decorators/non-exposed.d.ts +2 -0
- package/dist/decorators/non-exposed.js +24 -0
- package/dist/decorators/notification.d.ts +35 -0
- package/dist/decorators/notification.js +94 -0
- package/dist/decorators/projects.d.ts +32 -0
- package/dist/decorators/projects.js +87 -0
- package/dist/decorators/query.d.ts +2 -0
- package/dist/decorators/query.js +25 -0
- package/dist/decorators/read-model.d.ts +39 -0
- package/dist/decorators/read-model.js +129 -0
- package/dist/decorators/role.d.ts +6 -0
- package/dist/decorators/role.js +15 -0
- package/dist/decorators/scheduled-command.d.ts +9 -0
- package/dist/decorators/scheduled-command.js +25 -0
- package/dist/decorators/schema-migration.d.ts +36 -0
- package/dist/decorators/schema-migration.js +146 -0
- package/dist/decorators/sequenced-by.d.ts +28 -0
- package/dist/decorators/sequenced-by.js +79 -0
- package/dist/decorators/stage3-utils.d.ts +6 -0
- package/dist/decorators/stage3-utils.js +25 -0
- package/dist/delete-event-dispatcher.d.ts +4 -0
- package/dist/delete-event-dispatcher.js +23 -0
- package/dist/event-dispatcher.d.ts +9 -0
- package/dist/event-dispatcher.js +37 -0
- package/dist/event-processor.d.ts +15 -0
- package/dist/event-processor.js +125 -0
- package/dist/event-search.d.ts +2 -0
- package/dist/event-search.js +26 -0
- package/dist/event-stream-consumer.d.ts +7 -0
- package/dist/event-stream-consumer.js +36 -0
- package/dist/event-stream-producer.d.ts +7 -0
- package/dist/event-stream-producer.js +30 -0
- package/dist/events-reader.d.ts +11 -0
- package/dist/events-reader.js +63 -0
- package/dist/global-error-dispatcher.d.ts +16 -0
- package/dist/global-error-dispatcher.js +109 -0
- package/dist/graphql-dispatcher.d.ts +16 -0
- package/dist/graphql-dispatcher.js +195 -0
- package/dist/importer.d.ts +14 -0
- package/dist/importer.js +49 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +100 -0
- package/dist/injectable/index.d.ts +21 -0
- package/dist/injectable/index.js +2 -0
- package/dist/instrumentation/decorator/trace.d.ts +13 -0
- package/dist/instrumentation/decorator/trace.js +116 -0
- package/dist/instrumentation/index.d.ts +2 -0
- package/dist/instrumentation/index.js +5 -0
- package/dist/instrumentation/trace-notifier.d.ts +3 -0
- package/dist/instrumentation/trace-notifier.js +26 -0
- package/dist/magek.d.ts +42 -0
- package/dist/magek.js +158 -0
- package/dist/query-dispatcher.d.ts +8 -0
- package/dist/query-dispatcher.js +47 -0
- package/dist/read-model-schema-migrator.d.ts +14 -0
- package/dist/read-model-schema-migrator.js +80 -0
- package/dist/read-models-reader.d.ts +31 -0
- package/dist/read-models-reader.js +196 -0
- package/dist/register-handler.d.ts +11 -0
- package/dist/register-handler.js +95 -0
- package/dist/rocket-dispatcher.d.ts +6 -0
- package/dist/rocket-dispatcher.js +21 -0
- package/dist/scheduled-command-dispatcher.d.ts +12 -0
- package/dist/scheduled-command-dispatcher.js +54 -0
- package/dist/schema-migrator.d.ts +12 -0
- package/dist/schema-migrator.js +71 -0
- package/dist/sensor/health/health-indicators/database-events-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/database-events-health-indicator.js +26 -0
- package/dist/sensor/health/health-indicators/database-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/database-health-indicator.js +29 -0
- package/dist/sensor/health/health-indicators/database-read-models-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/database-read-models-health-indicator.js +26 -0
- package/dist/sensor/health/health-indicators/default-health-indicators.d.ts +5 -0
- package/dist/sensor/health/health-indicators/default-health-indicators.js +39 -0
- package/dist/sensor/health/health-indicators/function-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/function-health-indicator.js +30 -0
- package/dist/sensor/health/health-indicators/health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/health-indicator.js +30 -0
- package/dist/sensor/health/health-indicators/index.d.ts +3 -0
- package/dist/sensor/health/health-indicators/index.js +6 -0
- package/dist/sensor/health/health-indicators/os-info.d.ts +14 -0
- package/dist/sensor/health/health-indicators/os-info.js +38 -0
- package/dist/sensor/health/health-indicators/rockets-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/rockets-health-indicator.js +57 -0
- package/dist/sensor/health/health-indicators/version.d.ts +2 -0
- package/dist/sensor/health/health-indicators/version.js +24 -0
- package/dist/sensor/health/health-service.d.ts +22 -0
- package/dist/sensor/health/health-service.js +117 -0
- package/dist/sensor/health/health-utils.d.ts +7 -0
- package/dist/sensor/health/health-utils.js +53 -0
- package/dist/sensor/health/index.d.ts +3 -0
- package/dist/sensor/health/index.js +6 -0
- package/dist/sensor/index.d.ts +1 -0
- package/dist/sensor/index.js +4 -0
- package/dist/services/event-store.d.ts +27 -0
- package/dist/services/event-store.js +260 -0
- package/dist/services/filter-helpers.d.ts +3 -0
- package/dist/services/filter-helpers.js +19 -0
- package/dist/services/graphql/common.d.ts +26 -0
- package/dist/services/graphql/common.js +53 -0
- package/dist/services/graphql/graphql-generator.d.ts +46 -0
- package/dist/services/graphql/graphql-generator.js +269 -0
- package/dist/services/graphql/graphql-mutation-generator.d.ts +12 -0
- package/dist/services/graphql/graphql-mutation-generator.js +25 -0
- package/dist/services/graphql/graphql-query-generator.d.ts +22 -0
- package/dist/services/graphql/graphql-query-generator.js +39 -0
- package/dist/services/graphql/graphql-subcriptions-generator.d.ts +17 -0
- package/dist/services/graphql/graphql-subcriptions-generator.js +60 -0
- package/dist/services/graphql/graphql-type-informer.d.ts +23 -0
- package/dist/services/graphql/graphql-type-informer.js +160 -0
- package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.d.ts +14 -0
- package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +48 -0
- package/dist/services/graphql/query-generators/graphql-query-events-generator.d.ts +11 -0
- package/dist/services/graphql/query-generators/graphql-query-events-generator.js +68 -0
- package/dist/services/graphql/query-generators/graphql-query-filters-generator.d.ts +14 -0
- package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +31 -0
- package/dist/services/graphql/query-generators/graphql-query-generator.d.ts +12 -0
- package/dist/services/graphql/query-generators/graphql-query-generator.js +17 -0
- package/dist/services/graphql/query-generators/graphql-query-listed-generator.d.ts +16 -0
- package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +65 -0
- package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.d.ts +15 -0
- package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +65 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.d.ts +13 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +169 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.d.ts +11 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +28 -0
- package/dist/services/graphql/query-helpers/graphql-query-sort-builder.d.ts +12 -0
- package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +61 -0
- package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.d.ts +20 -0
- package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +127 -0
- package/dist/services/pub-sub/noop-read-model-pub-sub.d.ts +5 -0
- package/dist/services/pub-sub/noop-read-model-pub-sub.js +10 -0
- package/dist/services/pub-sub/read-model-pub-sub.d.ts +9 -0
- package/dist/services/pub-sub/read-model-pub-sub.js +112 -0
- package/dist/services/raw-events-parser.d.ts +5 -0
- package/dist/services/raw-events-parser.js +44 -0
- package/dist/services/read-model-searcher.d.ts +2 -0
- package/dist/services/read-model-searcher.js +11 -0
- package/dist/services/read-model-store.d.ts +41 -0
- package/dist/services/read-model-store.js +295 -0
- package/dist/services/token-verifiers/index.d.ts +4 -0
- package/dist/services/token-verifiers/index.js +7 -0
- package/dist/services/token-verifiers/jwks-uri-token-verifier.d.ts +21 -0
- package/dist/services/token-verifiers/jwks-uri-token-verifier.js +23 -0
- package/dist/services/token-verifiers/public-key-token-verifier.d.ts +13 -0
- package/dist/services/token-verifiers/public-key-token-verifier.js +19 -0
- package/dist/services/token-verifiers/role-based-token-verifier.d.ts +8 -0
- package/dist/services/token-verifiers/role-based-token-verifier.js +35 -0
- package/dist/services/token-verifiers/utilities.d.ts +31 -0
- package/dist/services/token-verifiers/utilities.js +70 -0
- package/dist/subscribers-notifier.d.ts +14 -0
- package/dist/subscribers-notifier.js +109 -0
- package/dist/token-verifier.d.ts +11 -0
- package/dist/token-verifier.js +46 -0
- package/dist/touch-entity-handler.d.ts +4 -0
- package/dist/touch-entity-handler.js +16 -0
- package/package.json +71 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekDeleteEventDispatcher = void 0;
|
|
4
|
+
const read_model_store_1 = require("./services/read-model-store");
|
|
5
|
+
class MagekDeleteEventDispatcher {
|
|
6
|
+
static async deleteEvent(config, parameters) {
|
|
7
|
+
const readModelStore = new read_model_store_1.ReadModelStore(config);
|
|
8
|
+
const events = await config.eventStore.findDeletableEvent(config, parameters);
|
|
9
|
+
if (!events || events.length === 0) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
for (const event of events) {
|
|
13
|
+
const snapshots = await config.eventStore.findDeletableSnapshot(config, event);
|
|
14
|
+
for (const snapshot of snapshots) {
|
|
15
|
+
await readModelStore.project(snapshot, true);
|
|
16
|
+
}
|
|
17
|
+
await config.eventStore.deleteSnapshot(config, snapshots);
|
|
18
|
+
}
|
|
19
|
+
await config.eventStore.deleteEvent(config, events);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.MagekDeleteEventDispatcher = MagekDeleteEventDispatcher;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MagekConfig } from '@magek/common';
|
|
2
|
+
export declare class MagekEventDispatcher {
|
|
3
|
+
/**
|
|
4
|
+
* Entry point to dispatch events.
|
|
5
|
+
* @param rawEvents List of raw events
|
|
6
|
+
* @param config
|
|
7
|
+
*/
|
|
8
|
+
static dispatch(rawEvents: unknown, config: MagekConfig): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekEventDispatcher = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@magek/common");
|
|
6
|
+
const event_store_1 = require("./services/event-store");
|
|
7
|
+
const raw_events_parser_1 = require("./services/raw-events-parser");
|
|
8
|
+
const read_model_store_1 = require("./services/read-model-store");
|
|
9
|
+
const instrumentation_1 = require("./instrumentation");
|
|
10
|
+
const event_processor_1 = require("./event-processor");
|
|
11
|
+
class MagekEventDispatcher {
|
|
12
|
+
/**
|
|
13
|
+
* Entry point to dispatch events.
|
|
14
|
+
* @param rawEvents List of raw events
|
|
15
|
+
* @param config
|
|
16
|
+
*/
|
|
17
|
+
static async dispatch(rawEvents, config) {
|
|
18
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
|
|
19
|
+
const eventStore = new event_store_1.EventStore(config);
|
|
20
|
+
const readModelStore = new read_model_store_1.ReadModelStore(config);
|
|
21
|
+
logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
|
|
22
|
+
try {
|
|
23
|
+
const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
|
|
24
|
+
await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
logger.error('Unhandled error while dispatching event: ', e);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.MagekEventDispatcher = MagekEventDispatcher;
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.DISPATCH_EVENTS),
|
|
34
|
+
tslib_1.__metadata("design:type", Function),
|
|
35
|
+
tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
|
|
36
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
37
|
+
], MagekEventDispatcher, "dispatch", null);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EventStore } from './services/event-store';
|
|
2
|
+
import { EventsStreamingCallback } from './services/raw-events-parser';
|
|
3
|
+
import { ReadModelStore } from './services/read-model-store';
|
|
4
|
+
export declare class MagekEventProcessor {
|
|
5
|
+
/**
|
|
6
|
+
* Function that will be called once for each entity from the `RawEventsParser.streamPerEntityEvents` method
|
|
7
|
+
* after the page of events is grouped by entity.
|
|
8
|
+
*/
|
|
9
|
+
static eventProcessor(eventStore: EventStore, readModelStore: ReadModelStore): EventsStreamingCallback;
|
|
10
|
+
private static filterDispatched;
|
|
11
|
+
private static snapshotAndUpdateReadModels;
|
|
12
|
+
private static dispatchEntityEventsToEventHandlers;
|
|
13
|
+
private static getEventInstance;
|
|
14
|
+
private static callEventHandler;
|
|
15
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekEventProcessor = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@magek/common");
|
|
6
|
+
const register_handler_1 = require("./register-handler");
|
|
7
|
+
const global_error_dispatcher_1 = require("./global-error-dispatcher");
|
|
8
|
+
const instrumentation_1 = require("./instrumentation");
|
|
9
|
+
const decorators_1 = require("./decorators");
|
|
10
|
+
class MagekEventProcessor {
|
|
11
|
+
/**
|
|
12
|
+
* Function that will be called once for each entity from the `RawEventsParser.streamPerEntityEvents` method
|
|
13
|
+
* after the page of events is grouped by entity.
|
|
14
|
+
*/
|
|
15
|
+
static eventProcessor(eventStore, readModelStore) {
|
|
16
|
+
return async (entityName, entityID, eventEnvelopes, config) => {
|
|
17
|
+
// Filter events that have already been dispatched
|
|
18
|
+
const eventsNotDispatched = await MagekEventProcessor.filterDispatched(config, eventEnvelopes, eventStore);
|
|
19
|
+
const eventEnvelopesProcessors = [
|
|
20
|
+
MagekEventProcessor.dispatchEntityEventsToEventHandlers(eventsNotDispatched, config),
|
|
21
|
+
];
|
|
22
|
+
// Read models are not updated for notification events (events that are not related to an entity but a topic)
|
|
23
|
+
if (!(entityName in config.topicToEvent)) {
|
|
24
|
+
eventEnvelopesProcessors.push(MagekEventProcessor.snapshotAndUpdateReadModels(config, entityName, entityID, eventStore, readModelStore));
|
|
25
|
+
}
|
|
26
|
+
await common_1.Promises.allSettledAndFulfilled(eventEnvelopesProcessors);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
static async filterDispatched(config, eventEnvelopes, eventStore) {
|
|
30
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#filterDispatched');
|
|
31
|
+
const filteredResults = await Promise.all(eventEnvelopes.map(async (eventEnvelope) => {
|
|
32
|
+
const result = await eventStore.storeDispatchedEvent(eventEnvelope);
|
|
33
|
+
if (!result) {
|
|
34
|
+
logger.warn('Event has already been dispatched. Skipping.', eventEnvelope);
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}));
|
|
38
|
+
return eventEnvelopes.filter((_, index) => filteredResults[index]);
|
|
39
|
+
}
|
|
40
|
+
static async snapshotAndUpdateReadModels(config, entityName, entityID, eventStore, readModelStore) {
|
|
41
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#snapshotAndUpdateReadModels');
|
|
42
|
+
let entitySnapshot = undefined;
|
|
43
|
+
try {
|
|
44
|
+
entitySnapshot = await eventStore.fetchEntitySnapshot(entityName, entityID);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
logger.error('Error while fetching or reducing entity snapshot:', e);
|
|
48
|
+
}
|
|
49
|
+
if (!entitySnapshot) {
|
|
50
|
+
logger.debug('No new snapshot generated, skipping read models projection');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
logger.debug('Snapshot loaded and started read models projection:', entitySnapshot);
|
|
54
|
+
await readModelStore.project(entitySnapshot);
|
|
55
|
+
}
|
|
56
|
+
static async dispatchEntityEventsToEventHandlers(entityEventEnvelopes, config) {
|
|
57
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher.dispatchEntityEventsToEventHandlers');
|
|
58
|
+
try {
|
|
59
|
+
await common_1.Promises.allSettledAndFulfilled(entityEventEnvelopes.map(async (eventEnvelope) => {
|
|
60
|
+
let eventHandlers = config.eventHandlers[eventEnvelope.typeName] || [];
|
|
61
|
+
const globalEventHandler = config.eventHandlers[decorators_1.GLOBAL_EVENT_HANDLERS];
|
|
62
|
+
if (globalEventHandler && globalEventHandler.length > 0) {
|
|
63
|
+
eventHandlers = eventHandlers.concat(globalEventHandler);
|
|
64
|
+
}
|
|
65
|
+
if (!eventHandlers || eventHandlers.length == 0) {
|
|
66
|
+
logger.debug(`No event-handlers found for event ${eventEnvelope.typeName}. Skipping...`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const eventInstance = this.getEventInstance(config, eventEnvelope);
|
|
70
|
+
if (eventHandlers && eventHandlers.length > 0) {
|
|
71
|
+
try {
|
|
72
|
+
await common_1.Promises.allSettledAndFulfilled(eventHandlers.map(async (eventHandler) => {
|
|
73
|
+
logger.debug('Calling "handle" method on event handler: ', eventHandler);
|
|
74
|
+
await this.callEventHandler(eventHandler, eventInstance, eventEnvelope, config);
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof common_1.PromisesError) {
|
|
79
|
+
logger.error(`Failed to process handlers for event ${eventEnvelope.typeName}:`, error.failedReasons);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
logger.error(`Unexpected error processing handlers for event ${eventEnvelope.typeName}:`, error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (error instanceof common_1.PromisesError) {
|
|
90
|
+
logger.error('Failed to process events:', error.failedReasons);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
logger.error('Unexpected error processing events:', error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
static getEventInstance(config, eventEnvelope) {
|
|
98
|
+
var _a;
|
|
99
|
+
const eventClass = (_a = config.events[eventEnvelope.typeName]) !== null && _a !== void 0 ? _a : config.notifications[eventEnvelope.typeName];
|
|
100
|
+
return (0, common_1.createInstance)(eventClass.class, eventEnvelope.value);
|
|
101
|
+
}
|
|
102
|
+
static async callEventHandler(eventHandler, eventInstance, eventEnvelope, config) {
|
|
103
|
+
const register = new common_1.Register(eventEnvelope.requestID, {}, register_handler_1.RegisterHandler.flush, eventEnvelope.currentUser);
|
|
104
|
+
try {
|
|
105
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventProcessor#handleEvent');
|
|
106
|
+
logger.debug('Calling "handle" method on event handler: ', eventHandler);
|
|
107
|
+
await eventHandler.handle(eventInstance, register);
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(config);
|
|
111
|
+
const error = await globalErrorDispatcher.dispatch(new common_1.EventHandlerGlobalError(eventEnvelope, eventInstance, e.eventHandlerMetadata, e));
|
|
112
|
+
if (error)
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
await register_handler_1.RegisterHandler.handle(config, register);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.MagekEventProcessor = MagekEventProcessor;
|
|
119
|
+
tslib_1.__decorate([
|
|
120
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.EVENT_HANDLERS_PROCESS),
|
|
121
|
+
tslib_1.__metadata("design:type", Function),
|
|
122
|
+
tslib_1.__metadata("design:paramtypes", [Array,
|
|
123
|
+
common_1.MagekConfig]),
|
|
124
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
125
|
+
], MagekEventProcessor, "dispatchEntityEventsToEventHandlers", null);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventSearch = eventSearch;
|
|
4
|
+
const common_1 = require("@magek/common");
|
|
5
|
+
async function eventSearch(config, request) {
|
|
6
|
+
const events = await config.eventStore.search(config, request);
|
|
7
|
+
return events.map((event) => createEventValueInstance(config, event));
|
|
8
|
+
}
|
|
9
|
+
function createEventValueInstance(config, event) {
|
|
10
|
+
const logger = (0, common_1.getLogger)(config, 'magek-event-search#createEventValueInstance');
|
|
11
|
+
const eventMetadata = config.events[event.type];
|
|
12
|
+
if (eventMetadata) {
|
|
13
|
+
event.value = (0, common_1.createInstance)(eventMetadata.class, event.value);
|
|
14
|
+
logger.debug(`Found @Event for "${event.type}". Created value instance`);
|
|
15
|
+
return event;
|
|
16
|
+
}
|
|
17
|
+
const notificationMetadata = config.notifications[event.type];
|
|
18
|
+
if (notificationMetadata) {
|
|
19
|
+
event.value = (0, common_1.createInstance)(notificationMetadata.class, event.value);
|
|
20
|
+
logger.debug(`Found @Notification for "${event.type}"`);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
logger.warn(`Could not find @Event or @Notification class for "${event.type}". Returned the event as it was`);
|
|
24
|
+
}
|
|
25
|
+
return event;
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MagekConfig } from '@magek/common';
|
|
2
|
+
/**
|
|
3
|
+
* This class consumes events from the event stream and dispatches them to the event handlers
|
|
4
|
+
*/
|
|
5
|
+
export declare class MagekEventStreamConsumer {
|
|
6
|
+
static consume(rawEvents: unknown, config: MagekConfig): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekEventStreamConsumer = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const instrumentation_1 = require("./instrumentation");
|
|
6
|
+
const common_1 = require("@magek/common");
|
|
7
|
+
const event_store_1 = require("./services/event-store");
|
|
8
|
+
const read_model_store_1 = require("./services/read-model-store");
|
|
9
|
+
const raw_events_parser_1 = require("./services/raw-events-parser");
|
|
10
|
+
const event_processor_1 = require("./event-processor");
|
|
11
|
+
/**
|
|
12
|
+
* This class consumes events from the event stream and dispatches them to the event handlers
|
|
13
|
+
*/
|
|
14
|
+
class MagekEventStreamConsumer {
|
|
15
|
+
static async consume(rawEvents, config) {
|
|
16
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
|
|
17
|
+
const eventStore = new event_store_1.EventStore(config);
|
|
18
|
+
const readModelStore = new read_model_store_1.ReadModelStore(config);
|
|
19
|
+
logger.debug('Stream event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
|
|
20
|
+
try {
|
|
21
|
+
const dedupEvents = await config.eventStore.dedupEventStream(config, rawEvents);
|
|
22
|
+
const eventEnvelopes = config.eventStore.rawStreamToEnvelopes(config, rawEvents, dedupEvents);
|
|
23
|
+
await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
logger.error('Unhandled error while consuming event: ', e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.MagekEventStreamConsumer = MagekEventStreamConsumer;
|
|
31
|
+
tslib_1.__decorate([
|
|
32
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.CONSUME_STREAM_EVENTS),
|
|
33
|
+
tslib_1.__metadata("design:type", Function),
|
|
34
|
+
tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
|
|
35
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
36
|
+
], MagekEventStreamConsumer, "consume", null);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekEventStreamProducer = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const instrumentation_1 = require("./instrumentation");
|
|
6
|
+
const common_1 = require("@magek/common");
|
|
7
|
+
const raw_events_parser_1 = require("./services/raw-events-parser");
|
|
8
|
+
/**
|
|
9
|
+
* Produces events to the event stream
|
|
10
|
+
*/
|
|
11
|
+
class MagekEventStreamProducer {
|
|
12
|
+
static async produce(request, config) {
|
|
13
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventStreamProducer#produce');
|
|
14
|
+
logger.debug('Produce event workflow started for request:', require('util').inspect(request, false, null, false));
|
|
15
|
+
try {
|
|
16
|
+
const eventEnvelopes = config.eventStore.rawToEnvelopes(request);
|
|
17
|
+
await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, config.eventStore.produce);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
logger.error('Unhandled error while producing events: ', e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.MagekEventStreamProducer = MagekEventStreamProducer;
|
|
25
|
+
tslib_1.__decorate([
|
|
26
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.PRODUCE_STREAM_EVENTS),
|
|
27
|
+
tslib_1.__metadata("design:type", Function),
|
|
28
|
+
tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
|
|
29
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
30
|
+
], MagekEventStreamProducer, "produce", null);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EventSearchRequest, MagekConfig, EventSearchResponse } from '@magek/common';
|
|
2
|
+
export declare class MagekEventsReader {
|
|
3
|
+
readonly config: MagekConfig;
|
|
4
|
+
constructor(config: MagekConfig);
|
|
5
|
+
fetch(eventRequest: EventSearchRequest): Promise<Array<EventSearchResponse>>;
|
|
6
|
+
private validateRequest;
|
|
7
|
+
private entityMetadataFromRequest;
|
|
8
|
+
private entityMetadataFromEntityName;
|
|
9
|
+
private entityMetadataFromEventName;
|
|
10
|
+
private processFetch;
|
|
11
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekEventsReader = void 0;
|
|
4
|
+
const common_1 = require("@magek/common");
|
|
5
|
+
const magek_1 = require("./magek");
|
|
6
|
+
class MagekEventsReader {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
}
|
|
10
|
+
async fetch(eventRequest) {
|
|
11
|
+
await this.validateRequest(eventRequest);
|
|
12
|
+
return this.processFetch(eventRequest);
|
|
13
|
+
}
|
|
14
|
+
async validateRequest(eventRequest) {
|
|
15
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekEventsReader#validateRequest');
|
|
16
|
+
logger.debug('Validating the following event request: ', eventRequest);
|
|
17
|
+
const entityMetadata = this.entityMetadataFromRequest(eventRequest);
|
|
18
|
+
await entityMetadata.eventStreamAuthorizer(eventRequest.currentUser, eventRequest);
|
|
19
|
+
}
|
|
20
|
+
entityMetadataFromRequest(eventRequest) {
|
|
21
|
+
const { parameters } = eventRequest;
|
|
22
|
+
if (!isByEntitySearch(parameters) && !isByEventTypeSearch(parameters)) {
|
|
23
|
+
throw new common_1.InvalidParameterError('Invalid event search request. It should contain either "type" or "entity" field, but it included none');
|
|
24
|
+
}
|
|
25
|
+
if (isByEntitySearch(parameters) && isByEventTypeSearch(parameters)) {
|
|
26
|
+
throw new common_1.InvalidParameterError('Invalid event search request. It should contain either "type" or "entity" field, but it included both');
|
|
27
|
+
}
|
|
28
|
+
if (isByEntitySearch(parameters)) {
|
|
29
|
+
return this.entityMetadataFromEntityName(parameters.entity);
|
|
30
|
+
}
|
|
31
|
+
if (isByEventTypeSearch(parameters)) {
|
|
32
|
+
return this.entityMetadataFromEventName(parameters.type);
|
|
33
|
+
}
|
|
34
|
+
// We would never reach this point
|
|
35
|
+
throw new common_1.InvalidParameterError('Could not determine event search kind');
|
|
36
|
+
}
|
|
37
|
+
entityMetadataFromEntityName(entityName) {
|
|
38
|
+
const entityMetadata = this.config.entities[entityName];
|
|
39
|
+
if (!entityMetadata) {
|
|
40
|
+
throw new common_1.NotFoundError(`Could not find entity metadata for "${entityName}"`);
|
|
41
|
+
}
|
|
42
|
+
return entityMetadata;
|
|
43
|
+
}
|
|
44
|
+
entityMetadataFromEventName(eventName) {
|
|
45
|
+
// All the events must be reduced by an entity, so we can get the associated entity from the
|
|
46
|
+
// reducers
|
|
47
|
+
const reducerMetadata = this.config.reducers[eventName];
|
|
48
|
+
if (!reducerMetadata) {
|
|
49
|
+
throw new common_1.NotFoundError(`Could not find the entity associated to event type "${eventName}"`);
|
|
50
|
+
}
|
|
51
|
+
return this.entityMetadataFromEntityName(reducerMetadata.class.name);
|
|
52
|
+
}
|
|
53
|
+
async processFetch(eventRequest) {
|
|
54
|
+
return magek_1.Magek.events(eventRequest.parameters);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.MagekEventsReader = MagekEventsReader;
|
|
58
|
+
function isByEntitySearch(parameters) {
|
|
59
|
+
return 'entity' in parameters;
|
|
60
|
+
}
|
|
61
|
+
function isByEventTypeSearch(parameters) {
|
|
62
|
+
return 'type' in parameters;
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MagekConfig, GlobalErrorHandlerInterface, GlobalErrorContainer } from '@magek/common';
|
|
2
|
+
export declare class MagekGlobalErrorDispatcher {
|
|
3
|
+
readonly config: MagekConfig;
|
|
4
|
+
readonly errorHandler: GlobalErrorHandlerInterface | undefined;
|
|
5
|
+
constructor(config: MagekConfig);
|
|
6
|
+
dispatch(error: GlobalErrorContainer): Promise<Error | undefined>;
|
|
7
|
+
private handleCommandError;
|
|
8
|
+
private handleQueryError;
|
|
9
|
+
private handleScheduleError;
|
|
10
|
+
private handleEventHandlerError;
|
|
11
|
+
private handleReducerError;
|
|
12
|
+
private handleProjectionError;
|
|
13
|
+
private handleSnapshotPersistError;
|
|
14
|
+
private handleEventError;
|
|
15
|
+
private handleGenericError;
|
|
16
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekGlobalErrorDispatcher = void 0;
|
|
4
|
+
const common_1 = require("@magek/common");
|
|
5
|
+
class MagekGlobalErrorDispatcher {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
var _a;
|
|
8
|
+
this.config = config;
|
|
9
|
+
this.errorHandler = (_a = this.config.globalErrorsHandler) === null || _a === void 0 ? void 0 : _a.class;
|
|
10
|
+
}
|
|
11
|
+
async dispatch(error) {
|
|
12
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekGlobalErrorDispatcher#dispatch');
|
|
13
|
+
if (!this.errorHandler)
|
|
14
|
+
return error.originalError;
|
|
15
|
+
let newError = error.originalError;
|
|
16
|
+
try {
|
|
17
|
+
switch (error.constructor) {
|
|
18
|
+
case common_1.CommandHandlerGlobalError:
|
|
19
|
+
newError = await this.handleCommandError(error);
|
|
20
|
+
break;
|
|
21
|
+
case common_1.QueryHandlerGlobalError:
|
|
22
|
+
newError = await this.handleQueryError(error);
|
|
23
|
+
break;
|
|
24
|
+
case common_1.ScheduleCommandGlobalError:
|
|
25
|
+
newError = await this.handleScheduleError(error);
|
|
26
|
+
break;
|
|
27
|
+
case common_1.EventHandlerGlobalError:
|
|
28
|
+
newError = await this.handleEventHandlerError(error);
|
|
29
|
+
break;
|
|
30
|
+
case common_1.ReducerGlobalError:
|
|
31
|
+
newError = await this.handleReducerError(error);
|
|
32
|
+
break;
|
|
33
|
+
case common_1.ProjectionGlobalError:
|
|
34
|
+
newError = await this.handleProjectionError(error);
|
|
35
|
+
break;
|
|
36
|
+
case common_1.SnapshotPersistHandlerGlobalError:
|
|
37
|
+
newError = await this.handleSnapshotPersistError(error);
|
|
38
|
+
break;
|
|
39
|
+
case common_1.EventGlobalError:
|
|
40
|
+
newError = await this.handleEventError(error);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
newError = await this.handleGenericError(newError);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
logger.error(`Unhandled error inside the global error handler. When handling error ${error.originalError}`, e);
|
|
47
|
+
return e;
|
|
48
|
+
}
|
|
49
|
+
if (newError)
|
|
50
|
+
return newError;
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
async handleCommandError(error) {
|
|
54
|
+
if (!this.errorHandler || !this.errorHandler.onCommandHandlerError)
|
|
55
|
+
throw error.originalError;
|
|
56
|
+
const currentError = error;
|
|
57
|
+
return await this.errorHandler.onCommandHandlerError(currentError.originalError, currentError.commandEnvelope, currentError.commandMetadata);
|
|
58
|
+
}
|
|
59
|
+
async handleQueryError(error) {
|
|
60
|
+
if (!this.errorHandler || !this.errorHandler.onQueryHandlerError)
|
|
61
|
+
throw error.originalError;
|
|
62
|
+
const currentError = error;
|
|
63
|
+
return await this.errorHandler.onQueryHandlerError(currentError.originalError, currentError.query);
|
|
64
|
+
}
|
|
65
|
+
async handleScheduleError(error) {
|
|
66
|
+
if (!this.errorHandler || !this.errorHandler.onScheduledCommandHandlerError)
|
|
67
|
+
throw error.originalError;
|
|
68
|
+
const currentError = error;
|
|
69
|
+
return await this.errorHandler.onScheduledCommandHandlerError(currentError.originalError, currentError.scheduleCommandEnvelope, currentError.scheduleCommandMetadata);
|
|
70
|
+
}
|
|
71
|
+
async handleEventHandlerError(error) {
|
|
72
|
+
if (!this.errorHandler || !this.errorHandler.onDispatchEventHandlerError)
|
|
73
|
+
throw error.originalError;
|
|
74
|
+
const currentError = error;
|
|
75
|
+
return await this.errorHandler.onDispatchEventHandlerError(currentError.originalError, currentError.eventEnvelope, currentError.eventHandlerMetadata, currentError.eventInstance);
|
|
76
|
+
}
|
|
77
|
+
async handleReducerError(error) {
|
|
78
|
+
if (!this.errorHandler || !this.errorHandler.onReducerError)
|
|
79
|
+
throw error.originalError;
|
|
80
|
+
const currentError = error;
|
|
81
|
+
return await this.errorHandler.onReducerError(currentError.originalError, currentError.eventEnvelope, currentError.reducerMetadata, currentError.eventInstance, currentError.snapshotInstance);
|
|
82
|
+
}
|
|
83
|
+
async handleProjectionError(error) {
|
|
84
|
+
if (!this.errorHandler || !this.errorHandler.onProjectionError)
|
|
85
|
+
throw error.originalError;
|
|
86
|
+
const currentError = error;
|
|
87
|
+
return await this.errorHandler.onProjectionError(currentError.originalError, currentError.entityEnvelope, currentError.projectionMetadata, currentError.entity, currentError.readModel);
|
|
88
|
+
}
|
|
89
|
+
async handleSnapshotPersistError(error) {
|
|
90
|
+
if (!this.errorHandler || !this.errorHandler.onSnapshotPersistError)
|
|
91
|
+
throw error.originalError;
|
|
92
|
+
const currentError = error;
|
|
93
|
+
return this.errorHandler.onSnapshotPersistError(currentError.originalError, currentError.snapshot);
|
|
94
|
+
}
|
|
95
|
+
async handleEventError(error) {
|
|
96
|
+
if (!this.errorHandler || !this.errorHandler.onEventError)
|
|
97
|
+
throw error.originalError;
|
|
98
|
+
const currentError = error;
|
|
99
|
+
return await this.errorHandler.onEventError(currentError.originalError, currentError.eventEnvelope);
|
|
100
|
+
}
|
|
101
|
+
async handleGenericError(error) {
|
|
102
|
+
if (!error)
|
|
103
|
+
return undefined;
|
|
104
|
+
if (!this.errorHandler || !this.errorHandler.onError)
|
|
105
|
+
throw error;
|
|
106
|
+
return await this.errorHandler.onError(error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.MagekGlobalErrorDispatcher = MagekGlobalErrorDispatcher;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MagekConfig } from '@magek/common';
|
|
2
|
+
export declare class MagekGraphQLDispatcher {
|
|
3
|
+
private config;
|
|
4
|
+
private readonly graphQLSchema;
|
|
5
|
+
private readonly websocketHandler;
|
|
6
|
+
private readonly readModelDispatcher;
|
|
7
|
+
private readonly tokenVerifier;
|
|
8
|
+
constructor(config: MagekConfig);
|
|
9
|
+
dispatch(request: unknown): Promise<unknown>;
|
|
10
|
+
private verifyTokenFromEnvelope;
|
|
11
|
+
private handleMessage;
|
|
12
|
+
private runGraphQLOperation;
|
|
13
|
+
private handleQueryOrMutation;
|
|
14
|
+
private handleSubscription;
|
|
15
|
+
private handleDisconnect;
|
|
16
|
+
}
|