@magek/server 0.0.7 → 0.0.8

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.
@@ -0,0 +1,18 @@
1
+ import { UserApp, MagekConfig } from '@magek/common';
2
+ /**
3
+ * Starts the event polling loop.
4
+ * Polls for unprocessed events and dispatches them via eventDispatcher.
5
+ *
6
+ * @param userApp - The user's Magek application module
7
+ * @param config - The Magek configuration object
8
+ */
9
+ export declare function startEventPolling(userApp: UserApp, config: MagekConfig): void;
10
+ /**
11
+ * Waits for the current poll cycle to complete.
12
+ * Exported for tests to ensure async poll callbacks finish before assertions.
13
+ */
14
+ export declare function waitForCurrentPoll(): Promise<void>;
15
+ /**
16
+ * Stops the event polling loop.
17
+ */
18
+ export declare function stopEventPolling(): void;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startEventPolling = startEventPolling;
4
+ exports.waitForCurrentPoll = waitForCurrentPoll;
5
+ exports.stopEventPolling = stopEventPolling;
6
+ const common_1 = require("@magek/common");
7
+ let pollingTimer = null;
8
+ let currentPollPromise = null;
9
+ /**
10
+ * Starts the event polling loop.
11
+ * Polls for unprocessed events and dispatches them via eventDispatcher.
12
+ *
13
+ * @param userApp - The user's Magek application module
14
+ * @param config - The Magek configuration object
15
+ */
16
+ function startEventPolling(userApp, config) {
17
+ const logger = (0, common_1.getLogger)(config, 'EventPoller');
18
+ const intervalMs = config.eventPollingIntervalMs;
19
+ logger.info(`Starting event polling every ${intervalMs}ms (batch size: ${config.eventProcessingBatchSize})`);
20
+ pollingTimer = setInterval(() => {
21
+ // Skip if previous poll is still running to prevent overlapping executions
22
+ if (currentPollPromise) {
23
+ return;
24
+ }
25
+ // Store the promise so tests can await it and we can prevent overlap
26
+ currentPollPromise = pollAndProcessEvents(userApp, config, logger).finally(() => {
27
+ currentPollPromise = null;
28
+ });
29
+ }, intervalMs);
30
+ }
31
+ /**
32
+ * Waits for the current poll cycle to complete.
33
+ * Exported for tests to ensure async poll callbacks finish before assertions.
34
+ */
35
+ async function waitForCurrentPoll() {
36
+ if (currentPollPromise) {
37
+ await currentPollPromise;
38
+ }
39
+ }
40
+ /**
41
+ * Stops the event polling loop.
42
+ */
43
+ function stopEventPolling() {
44
+ if (pollingTimer) {
45
+ clearInterval(pollingTimer);
46
+ pollingTimer = null;
47
+ }
48
+ currentPollPromise = null;
49
+ }
50
+ async function pollAndProcessEvents(userApp, config, logger) {
51
+ const eventStore = config.eventStore;
52
+ // Check if adapter supports async processing
53
+ if (!eventStore.fetchUnprocessedEvents || !eventStore.markEventProcessed) {
54
+ return;
55
+ }
56
+ try {
57
+ const events = await eventStore.fetchUnprocessedEvents(config);
58
+ if (events.length === 0) {
59
+ return;
60
+ }
61
+ logger.debug(`Processing ${events.length} events`);
62
+ // Process each event individually
63
+ for (const event of events) {
64
+ try {
65
+ // Dispatch the event
66
+ await userApp.eventDispatcher([event]);
67
+ // Mark as processed only after successful dispatch
68
+ if (event.id) {
69
+ await eventStore.markEventProcessed(config, event.id);
70
+ }
71
+ }
72
+ catch (error) {
73
+ logger.error(`Error processing event ${event.id}:`, error);
74
+ // Stop processing on first error to maintain order
75
+ break;
76
+ }
77
+ }
78
+ }
79
+ catch (error) {
80
+ logger.error('Error during event polling:', error);
81
+ }
82
+ }
@@ -0,0 +1,2 @@
1
+ export declare const MAGEK_LOCAL_PORT = "INTERNAL_LOCAL_PORT";
2
+ export declare const localPort: () => string;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.localPort = exports.MAGEK_LOCAL_PORT = void 0;
4
+ exports.MAGEK_LOCAL_PORT = 'INTERNAL_LOCAL_PORT';
5
+ const localPort = () => process.env[exports.MAGEK_LOCAL_PORT] || '3000';
6
+ exports.localPort = localPort;
@@ -8,6 +8,7 @@ exports.isGraphQLFunctionUp = isGraphQLFunctionUp;
8
8
  exports.rawRequestToSensorHealth = rawRequestToSensorHealth;
9
9
  const paths_1 = require("../paths");
10
10
  const common_1 = require("@magek/common");
11
+ const internal_info_1 = require("../internal-info");
11
12
  const fs_1 = require("fs");
12
13
  async function databaseUrl() {
13
14
  return [paths_1.eventsDatabase, paths_1.readModelsDatabase];
@@ -19,7 +20,7 @@ async function countAll(database) {
19
20
  }
20
21
  async function graphqlFunctionUrl() {
21
22
  try {
22
- const port = (0, common_1.localPort)();
23
+ const port = (0, internal_info_1.localPort)();
23
24
  return `http://localhost:${port}/graphql`;
24
25
  }
25
26
  catch (e) {
package/dist/server.js CHANGED
@@ -13,6 +13,7 @@ const health_controller_1 = require("./infrastructure/controllers/health-control
13
13
  const websocket_registry_1 = require("./infrastructure/websocket-registry");
14
14
  const http_1 = require("./infrastructure/http");
15
15
  const scheduler_1 = require("./infrastructure/scheduler");
16
+ const event_poller_1 = require("./infrastructure/event-poller");
16
17
  // Global WebSocket registry instance
17
18
  let globalWebSocketRegistry;
18
19
  /**
@@ -191,6 +192,11 @@ async function createServer(userApp, options = {}) {
191
192
  const config = userApp.Magek.config;
192
193
  if (config) {
193
194
  (0, scheduler_1.configureScheduler)(config, userApp);
195
+ (0, event_poller_1.startEventPolling)(userApp, config);
196
+ // Clean up event polling when server shuts down
197
+ fastify.addHook('onClose', async () => {
198
+ (0, event_poller_1.stopEventPolling)();
199
+ });
194
200
  }
195
201
  await fastify.ready();
196
202
  return fastify;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magek/server",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Debug your Magek projects locally",
5
5
  "keywords": [
6
6
  "server"
@@ -26,20 +26,30 @@
26
26
  "node": ">=22.0.0 <23.0.0"
27
27
  },
28
28
  "dependencies": {
29
- "@magek/common": "^0.0.7",
29
+ "@magek/common": "workspace:^0.0.8",
30
30
  "@fastify/cors": "11.2.0",
31
31
  "@fastify/websocket": "11.2.0",
32
32
  "@seald-io/nedb": "4.1.2",
33
- "fastify": "5.7.2",
33
+ "fastify": "5.7.3",
34
34
  "fastify-sse-v2": "4.2.2",
35
35
  "node-schedule": "2.1.1",
36
36
  "tslib": "2.8.1"
37
37
  },
38
+ "scripts": {
39
+ "format": "prettier --write --ext '.js,.ts' **/*.ts **/*/*.ts",
40
+ "lint:check": "eslint \"**/*.ts\"",
41
+ "lint:fix": "eslint --quiet --fix \"**/*.ts\"",
42
+ "build": "tsc -b tsconfig.json",
43
+ "clean": "rimraf ./dist tsconfig.tsbuildinfo",
44
+ "prepack": "tsc -b tsconfig.json",
45
+ "test:provider-local": "npm run test",
46
+ "test": "tsc --noEmit -p tsconfig.test.json && MAGEK_ENV=test c8 mocha --forbid-only \"test/**/*.test.ts\""
47
+ },
38
48
  "bugs": {
39
49
  "url": "https://github.com/theam/magek/issues"
40
50
  },
41
51
  "devDependencies": {
42
- "@magek/eslint-config": "^0.0.7",
52
+ "@magek/eslint-config": "workspace:^0.0.8",
43
53
  "@types/chai": "5.2.3",
44
54
  "@types/chai-as-promised": "8.0.2",
45
55
  "@types/mocha": "10.0.10",
@@ -57,14 +67,5 @@
57
67
  "sinon-chai": "4.0.1",
58
68
  "tsx": "^4.19.2",
59
69
  "typescript": "5.9.3"
60
- },
61
- "scripts": {
62
- "format": "prettier --write --ext '.js,.ts' **/*.ts **/*/*.ts",
63
- "lint:check": "eslint \"**/*.ts\"",
64
- "lint:fix": "eslint --quiet --fix \"**/*.ts\"",
65
- "build": "tsc -b tsconfig.json",
66
- "clean": "rimraf ./dist tsconfig.tsbuildinfo",
67
- "test:provider-local": "npm run test",
68
- "test": "tsc --noEmit -p tsconfig.test.json && MAGEK_ENV=test c8 mocha --forbid-only \"test/**/*.test.ts\""
69
70
  }
70
- }
71
+ }