motia 0.11.1-beta.156-879726 → 0.11.1-beta.156-960492

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 (34) hide show
  1. package/dist/cjs/cloud/new-deployment/build.js +1 -3
  2. package/dist/cjs/dev.js +11 -9
  3. package/dist/cjs/generate-locked-data.d.ts +0 -2
  4. package/dist/cjs/generate-locked-data.js +2 -2
  5. package/dist/cjs/generate-types.js +1 -3
  6. package/dist/cjs/start.js +3 -9
  7. package/dist/esm/cloud/new-deployment/build.js +1 -3
  8. package/dist/esm/dev.js +9 -10
  9. package/dist/esm/generate-locked-data.d.ts +0 -2
  10. package/dist/esm/generate-locked-data.js +2 -2
  11. package/dist/esm/generate-types.js +1 -3
  12. package/dist/esm/start.js +4 -10
  13. package/dist/types/generate-locked-data.d.ts +0 -2
  14. package/package.json +4 -8
  15. package/dist/cjs/__tests__/redis-memory-manager.test.d.ts +0 -1
  16. package/dist/cjs/__tests__/redis-memory-manager.test.js +0 -175
  17. package/dist/cjs/__tests__/test-helpers/redis-test-helper.d.ts +0 -51
  18. package/dist/cjs/__tests__/test-helpers/redis-test-helper.example.test.d.ts +0 -1
  19. package/dist/cjs/__tests__/test-helpers/redis-test-helper.example.test.js +0 -83
  20. package/dist/cjs/__tests__/test-helpers/redis-test-helper.js +0 -101
  21. package/dist/cjs/redis-memory-manager.d.ts +0 -7
  22. package/dist/cjs/redis-memory-manager.js +0 -122
  23. package/dist/esm/__tests__/redis-memory-manager.test.d.ts +0 -1
  24. package/dist/esm/__tests__/redis-memory-manager.test.js +0 -173
  25. package/dist/esm/__tests__/test-helpers/redis-test-helper.d.ts +0 -51
  26. package/dist/esm/__tests__/test-helpers/redis-test-helper.example.test.d.ts +0 -1
  27. package/dist/esm/__tests__/test-helpers/redis-test-helper.example.test.js +0 -81
  28. package/dist/esm/__tests__/test-helpers/redis-test-helper.js +0 -94
  29. package/dist/esm/redis-memory-manager.d.ts +0 -7
  30. package/dist/esm/redis-memory-manager.js +0 -117
  31. package/dist/types/__tests__/redis-memory-manager.test.d.ts +0 -1
  32. package/dist/types/__tests__/test-helpers/redis-test-helper.d.ts +0 -51
  33. package/dist/types/__tests__/test-helpers/redis-test-helper.example.test.d.ts +0 -1
  34. package/dist/types/redis-memory-manager.d.ts +0 -7
@@ -8,7 +8,6 @@ const core_1 = require("@motiadev/core");
8
8
  const printer_1 = require("@motiadev/core/dist/src/printer");
9
9
  const fs_1 = __importDefault(require("fs"));
10
10
  const generate_locked_data_1 = require("../../generate-locked-data");
11
- const redis_memory_manager_1 = require("../../redis-memory-manager");
12
11
  const build_error_1 = require("../../utils/errors/build.error");
13
12
  const builder_1 = require("../build/builder");
14
13
  const node_1 = require("../build/builders/node");
@@ -27,8 +26,7 @@ const build = async (listener) => {
27
26
  builder.registerBuilder('node', new node_1.NodeBuilder(builder, listener));
28
27
  fs_1.default.rmSync(constants_1.distDir, { recursive: true, force: true });
29
28
  fs_1.default.mkdirSync(constants_1.distDir, { recursive: true });
30
- const redisClient = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(constants_1.projectDir, false);
31
- const lockedData = new core_1.LockedData(constants_1.projectDir, new core_1.MemoryStreamAdapterManager(), new printer_1.NoPrinter(), redisClient);
29
+ const lockedData = new core_1.LockedData(constants_1.projectDir, new core_1.MemoryStreamAdapterManager(), new printer_1.NoPrinter());
32
30
  if (hasPythonSteps(stepFiles)) {
33
31
  builder.registerBuilder('python', new python_1.PythonBuilder(builder, listener));
34
32
  }
package/dist/cjs/dev.js CHANGED
@@ -1,17 +1,18 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.dev = void 0;
4
7
  const analytics_node_1 = require("@amplitude/analytics-node");
5
- const adapter_redis_state_1 = require("@motiadev/adapter-redis-state");
6
- const adapter_redis_streams_1 = require("@motiadev/adapter-redis-streams");
7
8
  const core_1 = require("@motiadev/core");
9
+ const path_1 = __importDefault(require("path"));
8
10
  const endpoints_1 = require("./cloud/endpoints");
9
11
  const constants_1 = require("./constants");
10
12
  const dev_watchers_1 = require("./dev-watchers");
11
13
  const generate_locked_data_1 = require("./generate-locked-data");
12
14
  const load_motia_config_1 = require("./load-motia-config");
13
15
  const plugins_1 = require("./plugins");
14
- const redis_memory_manager_1 = require("./redis-memory-manager");
15
16
  const activate_python_env_1 = require("./utils/activate-python-env");
16
17
  const analytics_1 = require("./utils/analytics");
17
18
  const version_1 = require("./version");
@@ -40,18 +41,20 @@ const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFileStora
40
41
  }
41
42
  const motiaFileStoragePath = motiaFileStorageDir || '.motia';
42
43
  const appConfig = await (0, load_motia_config_1.loadMotiaConfig)(baseDir);
43
- const redisClient = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(motiaFileStoragePath, true);
44
44
  const adapters = {
45
45
  eventAdapter: appConfig.adapters?.events || new core_1.DefaultQueueEventAdapter(),
46
46
  cronAdapter: appConfig.adapters?.cron || new core_1.DefaultCronAdapter(),
47
- streamAdapter: appConfig.adapters?.streams || new adapter_redis_streams_1.RedisStreamAdapterManager(redisClient),
47
+ streamAdapter: appConfig.adapters?.streams || new core_1.FileStreamAdapterManager(baseDir, motiaFileStoragePath),
48
48
  };
49
49
  const lockedData = await (0, generate_locked_data_1.generateLockedData)({
50
50
  projectDir: baseDir,
51
51
  streamAdapter: adapters.streamAdapter,
52
- redisClient,
53
52
  });
54
- const state = appConfig.adapters?.state || new adapter_redis_state_1.RedisStateAdapter(redisClient);
53
+ const state = appConfig.adapters?.state ||
54
+ (0, core_1.createStateAdapter)({
55
+ adapter: 'default',
56
+ filePath: path_1.default.join(baseDir, motiaFileStoragePath),
57
+ });
55
58
  const config = { isVerbose };
56
59
  const motiaServer = (0, core_1.createServer)(lockedData, state, config, adapters, appConfig.app);
57
60
  const watcher = (0, dev_watchers_1.createDevWatchers)(lockedData, motiaServer, motiaServer.motiaEventManager, motiaServer.cronManager);
@@ -98,11 +101,11 @@ const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFileStora
98
101
  motiaServer.server.listen(port, hostname);
99
102
  console.log('🚀 Server ready and listening on port', port);
100
103
  console.log(`🔗 Open http://localhost:${port}${constants_1.workbenchBase} to open workbench 🛠️`);
104
+ // 6) Gracefully shut down on SIGTERM
101
105
  process.on('SIGTERM', async () => {
102
106
  (0, core_1.trackEvent)('dev_server_shutdown', { reason: 'SIGTERM' });
103
107
  motiaServer.server.close();
104
108
  await watcher.stop();
105
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
106
109
  await (0, analytics_node_1.flush)().promise;
107
110
  process.exit(0);
108
111
  });
@@ -110,7 +113,6 @@ const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFileStora
110
113
  (0, core_1.trackEvent)('dev_server_shutdown', { reason: 'SIGINT' });
111
114
  motiaServer.server.close();
112
115
  await watcher.stop();
113
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
114
116
  await (0, analytics_node_1.flush)().promise;
115
117
  process.exit(0);
116
118
  });
@@ -1,11 +1,9 @@
1
1
  import { LockedData, type Step, type StreamAdapterManager } from '@motiadev/core';
2
- import type { RedisClientType } from 'redis';
3
2
  export declare const getStepFiles: (projectDir: string) => string[];
4
3
  export declare const getStreamFiles: (projectDir: string) => string[];
5
4
  export declare const collectFlows: (projectDir: string, lockedData: LockedData) => Promise<Step[]>;
6
5
  export declare const generateLockedData: (config: {
7
6
  projectDir: string;
8
7
  streamAdapter: StreamAdapterManager;
9
- redisClient: RedisClientType;
10
8
  printerType?: "disabled" | "default";
11
9
  }) => Promise<LockedData>;
@@ -108,13 +108,13 @@ const collectFlows = async (projectDir, lockedData) => {
108
108
  exports.collectFlows = collectFlows;
109
109
  const generateLockedData = async (config) => {
110
110
  try {
111
- const { projectDir, streamAdapter, printerType = 'default', redisClient } = config;
111
+ const { projectDir, streamAdapter, printerType = 'default' } = config;
112
112
  const printer = printerType === 'disabled' ? new printer_1.NoPrinter() : new printer_1.Printer(projectDir);
113
113
  /*
114
114
  * NOTE: right now for performance and simplicity let's enforce a folder,
115
115
  * but we might want to remove this and scan the entire current directory
116
116
  */
117
- const lockedData = new core_1.LockedData(projectDir, streamAdapter, printer, redisClient);
117
+ const lockedData = new core_1.LockedData(projectDir, streamAdapter, printer);
118
118
  await (0, exports.collectFlows)(projectDir, lockedData);
119
119
  lockedData.saveTypes();
120
120
  return lockedData;
@@ -4,13 +4,11 @@ exports.generateTypes = void 0;
4
4
  const core_1 = require("@motiadev/core");
5
5
  const crypto_1 = require("crypto");
6
6
  const generate_locked_data_1 = require("./generate-locked-data");
7
- const redis_memory_manager_1 = require("./redis-memory-manager");
8
7
  const version = `${(0, crypto_1.randomUUID)()}:${Math.floor(Date.now() / 1000)}`;
9
8
  const generateTypes = async (projectDir) => {
10
9
  const files = (0, generate_locked_data_1.getStepFiles)(projectDir);
11
10
  const streamsFiles = (0, generate_locked_data_1.getStreamFiles)(projectDir);
12
- const redisClient = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(projectDir, false);
13
- const lockedData = new core_1.LockedData(projectDir, new core_1.MemoryStreamAdapterManager(), new core_1.Printer(projectDir), redisClient);
11
+ const lockedData = new core_1.LockedData(projectDir, new core_1.MemoryStreamAdapterManager(), new core_1.Printer(projectDir));
14
12
  for (const filePath of files) {
15
13
  const config = await (0, core_1.getStepConfig)(filePath, projectDir);
16
14
  if (config) {
package/dist/cjs/start.js CHANGED
@@ -4,15 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.start = void 0;
7
- const adapter_redis_state_1 = require("@motiadev/adapter-redis-state");
8
- const adapter_redis_streams_1 = require("@motiadev/adapter-redis-streams");
9
7
  const core_1 = require("@motiadev/core");
10
8
  const path_1 = __importDefault(require("path"));
11
9
  const constants_1 = require("./constants");
12
10
  const generate_locked_data_1 = require("./generate-locked-data");
13
11
  const load_motia_config_1 = require("./load-motia-config");
14
12
  const plugins_1 = require("./plugins");
15
- const redis_memory_manager_1 = require("./redis-memory-manager");
16
13
  const activate_python_env_1 = require("./utils/activate-python-env");
17
14
  const version_1 = require("./version");
18
15
  require('ts-node').register({
@@ -31,18 +28,16 @@ const start = async (port, hostname, disableVerbose, motiaFileStorageDir) => {
31
28
  const motiaFileStoragePath = motiaFileStorageDir || '.motia';
32
29
  const dotMotia = path_1.default.join(baseDir, motiaFileStoragePath);
33
30
  const appConfig = await (0, load_motia_config_1.loadMotiaConfig)(baseDir);
34
- const redisClient = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(dotMotia);
35
31
  const adapters = {
36
32
  eventAdapter: appConfig.adapters?.events || new core_1.DefaultQueueEventAdapter(),
37
33
  cronAdapter: appConfig.adapters?.cron || new core_1.DefaultCronAdapter(),
38
- streamAdapter: appConfig.adapters?.streams || new adapter_redis_streams_1.RedisStreamAdapterManager(redisClient),
34
+ streamAdapter: appConfig.adapters?.streams || new core_1.FileStreamAdapterManager(baseDir),
39
35
  };
40
36
  const lockedData = await (0, generate_locked_data_1.generateLockedData)({
41
37
  projectDir: baseDir,
42
38
  streamAdapter: adapters.streamAdapter,
43
- redisClient,
44
39
  });
45
- const state = appConfig.adapters?.state || new adapter_redis_state_1.RedisStateAdapter(redisClient);
40
+ const state = appConfig.adapters?.state || (0, core_1.createStateAdapter)({ adapter: 'default', filePath: dotMotia });
46
41
  const config = { isVerbose, isDev: false, version: version_1.version };
47
42
  const motiaServer = (0, core_1.createServer)(lockedData, state, config, adapters, appConfig.app);
48
43
  const plugins = await (0, plugins_1.processPlugins)(motiaServer);
@@ -58,14 +53,13 @@ const start = async (port, hostname, disableVerbose, motiaFileStorageDir) => {
58
53
  motiaServer.server.listen(port, hostname);
59
54
  console.log('🚀 Server ready and listening on port', port);
60
55
  console.log(`🔗 Open http://${hostname}:${port}${constants_1.workbenchBase} to open workbench 🛠️`);
56
+ // 6) Gracefully shut down on SIGTERM
61
57
  process.on('SIGTERM', async () => {
62
58
  motiaServer.server.close();
63
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
64
59
  process.exit(0);
65
60
  });
66
61
  process.on('SIGINT', async () => {
67
62
  motiaServer.server.close();
68
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
69
63
  process.exit(0);
70
64
  });
71
65
  };
@@ -2,7 +2,6 @@ import { isApiStep, LockedData, MemoryStreamAdapterManager } from '@motiadev/cor
2
2
  import { NoPrinter } from '@motiadev/core/dist/src/printer';
3
3
  import fs from 'fs';
4
4
  import { collectFlows, getStepFiles } from '../../generate-locked-data';
5
- import { instanceRedisMemoryServer } from '../../redis-memory-manager';
6
5
  import { BuildError, BuildErrorType } from '../../utils/errors/build.error';
7
6
  import { Builder } from '../build/builder';
8
7
  import { NodeBuilder } from '../build/builders/node';
@@ -21,8 +20,7 @@ export const build = async (listener) => {
21
20
  builder.registerBuilder('node', new NodeBuilder(builder, listener));
22
21
  fs.rmSync(distDir, { recursive: true, force: true });
23
22
  fs.mkdirSync(distDir, { recursive: true });
24
- const redisClient = await instanceRedisMemoryServer(projectDir, false);
25
- const lockedData = new LockedData(projectDir, new MemoryStreamAdapterManager(), new NoPrinter(), redisClient);
23
+ const lockedData = new LockedData(projectDir, new MemoryStreamAdapterManager(), new NoPrinter());
26
24
  if (hasPythonSteps(stepFiles)) {
27
25
  builder.registerBuilder('python', new PythonBuilder(builder, listener));
28
26
  }
package/dist/esm/dev.js CHANGED
@@ -1,14 +1,12 @@
1
1
  import { flush } from '@amplitude/analytics-node';
2
- import { RedisStateAdapter } from '@motiadev/adapter-redis-state';
3
- import { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams';
4
- import { createMermaidGenerator, createServer, DefaultCronAdapter, DefaultQueueEventAdapter, getProjectIdentifier, trackEvent, } from '@motiadev/core';
2
+ import { createMermaidGenerator, createServer, createStateAdapter, DefaultCronAdapter, DefaultQueueEventAdapter, FileStreamAdapterManager, getProjectIdentifier, trackEvent, } from '@motiadev/core';
3
+ import path from 'path';
5
4
  import { deployEndpoints } from './cloud/endpoints';
6
5
  import { isTutorialDisabled, workbenchBase } from './constants';
7
6
  import { createDevWatchers } from './dev-watchers';
8
7
  import { generateLockedData, getStepFiles } from './generate-locked-data';
9
8
  import { loadMotiaConfig } from './load-motia-config';
10
9
  import { processPlugins } from './plugins';
11
- import { instanceRedisMemoryServer, stopRedisMemoryServer } from './redis-memory-manager';
12
10
  import { activatePythonVenv } from './utils/activate-python-env';
13
11
  import { identifyUser } from './utils/analytics';
14
12
  import { version } from './version';
@@ -37,18 +35,20 @@ export const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFi
37
35
  }
38
36
  const motiaFileStoragePath = motiaFileStorageDir || '.motia';
39
37
  const appConfig = await loadMotiaConfig(baseDir);
40
- const redisClient = await instanceRedisMemoryServer(motiaFileStoragePath, true);
41
38
  const adapters = {
42
39
  eventAdapter: appConfig.adapters?.events || new DefaultQueueEventAdapter(),
43
40
  cronAdapter: appConfig.adapters?.cron || new DefaultCronAdapter(),
44
- streamAdapter: appConfig.adapters?.streams || new RedisStreamAdapterManager(redisClient),
41
+ streamAdapter: appConfig.adapters?.streams || new FileStreamAdapterManager(baseDir, motiaFileStoragePath),
45
42
  };
46
43
  const lockedData = await generateLockedData({
47
44
  projectDir: baseDir,
48
45
  streamAdapter: adapters.streamAdapter,
49
- redisClient,
50
46
  });
51
- const state = appConfig.adapters?.state || new RedisStateAdapter(redisClient);
47
+ const state = appConfig.adapters?.state ||
48
+ createStateAdapter({
49
+ adapter: 'default',
50
+ filePath: path.join(baseDir, motiaFileStoragePath),
51
+ });
52
52
  const config = { isVerbose };
53
53
  const motiaServer = createServer(lockedData, state, config, adapters, appConfig.app);
54
54
  const watcher = createDevWatchers(lockedData, motiaServer, motiaServer.motiaEventManager, motiaServer.cronManager);
@@ -95,11 +95,11 @@ export const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFi
95
95
  motiaServer.server.listen(port, hostname);
96
96
  console.log('🚀 Server ready and listening on port', port);
97
97
  console.log(`🔗 Open http://localhost:${port}${workbenchBase} to open workbench 🛠️`);
98
+ // 6) Gracefully shut down on SIGTERM
98
99
  process.on('SIGTERM', async () => {
99
100
  trackEvent('dev_server_shutdown', { reason: 'SIGTERM' });
100
101
  motiaServer.server.close();
101
102
  await watcher.stop();
102
- await stopRedisMemoryServer();
103
103
  await flush().promise;
104
104
  process.exit(0);
105
105
  });
@@ -107,7 +107,6 @@ export const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFi
107
107
  trackEvent('dev_server_shutdown', { reason: 'SIGINT' });
108
108
  motiaServer.server.close();
109
109
  await watcher.stop();
110
- await stopRedisMemoryServer();
111
110
  await flush().promise;
112
111
  process.exit(0);
113
112
  });
@@ -1,11 +1,9 @@
1
1
  import { LockedData, type Step, type StreamAdapterManager } from '@motiadev/core';
2
- import type { RedisClientType } from 'redis';
3
2
  export declare const getStepFiles: (projectDir: string) => string[];
4
3
  export declare const getStreamFiles: (projectDir: string) => string[];
5
4
  export declare const collectFlows: (projectDir: string, lockedData: LockedData) => Promise<Step[]>;
6
5
  export declare const generateLockedData: (config: {
7
6
  projectDir: string;
8
7
  streamAdapter: StreamAdapterManager;
9
- redisClient: RedisClientType;
10
8
  printerType?: "disabled" | "default";
11
9
  }) => Promise<LockedData>;
@@ -99,13 +99,13 @@ export const collectFlows = async (projectDir, lockedData) => {
99
99
  };
100
100
  export const generateLockedData = async (config) => {
101
101
  try {
102
- const { projectDir, streamAdapter, printerType = 'default', redisClient } = config;
102
+ const { projectDir, streamAdapter, printerType = 'default' } = config;
103
103
  const printer = printerType === 'disabled' ? new NoPrinter() : new Printer(projectDir);
104
104
  /*
105
105
  * NOTE: right now for performance and simplicity let's enforce a folder,
106
106
  * but we might want to remove this and scan the entire current directory
107
107
  */
108
- const lockedData = new LockedData(projectDir, streamAdapter, printer, redisClient);
108
+ const lockedData = new LockedData(projectDir, streamAdapter, printer);
109
109
  await collectFlows(projectDir, lockedData);
110
110
  lockedData.saveTypes();
111
111
  return lockedData;
@@ -1,13 +1,11 @@
1
1
  import { getStepConfig, getStreamConfig, LockedData, MemoryStreamAdapterManager, Printer } from '@motiadev/core';
2
2
  import { randomUUID } from 'crypto';
3
3
  import { getStepFiles, getStreamFiles } from './generate-locked-data';
4
- import { instanceRedisMemoryServer } from './redis-memory-manager';
5
4
  const version = `${randomUUID()}:${Math.floor(Date.now() / 1000)}`;
6
5
  export const generateTypes = async (projectDir) => {
7
6
  const files = getStepFiles(projectDir);
8
7
  const streamsFiles = getStreamFiles(projectDir);
9
- const redisClient = await instanceRedisMemoryServer(projectDir, false);
10
- const lockedData = new LockedData(projectDir, new MemoryStreamAdapterManager(), new Printer(projectDir), redisClient);
8
+ const lockedData = new LockedData(projectDir, new MemoryStreamAdapterManager(), new Printer(projectDir));
11
9
  for (const filePath of files) {
12
10
  const config = await getStepConfig(filePath, projectDir);
13
11
  if (config) {
package/dist/esm/start.js CHANGED
@@ -1,12 +1,9 @@
1
- import { RedisStateAdapter } from '@motiadev/adapter-redis-state';
2
- import { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams';
3
- import { createServer, DefaultCronAdapter, DefaultQueueEventAdapter } from '@motiadev/core';
1
+ import { createServer, createStateAdapter, DefaultCronAdapter, DefaultQueueEventAdapter, FileStreamAdapterManager, } from '@motiadev/core';
4
2
  import path from 'path';
5
3
  import { workbenchBase } from './constants';
6
4
  import { generateLockedData, getStepFiles } from './generate-locked-data';
7
5
  import { loadMotiaConfig } from './load-motia-config';
8
6
  import { processPlugins } from './plugins';
9
- import { instanceRedisMemoryServer, stopRedisMemoryServer } from './redis-memory-manager';
10
7
  import { activatePythonVenv } from './utils/activate-python-env';
11
8
  import { version } from './version';
12
9
  require('ts-node').register({
@@ -25,18 +22,16 @@ export const start = async (port, hostname, disableVerbose, motiaFileStorageDir)
25
22
  const motiaFileStoragePath = motiaFileStorageDir || '.motia';
26
23
  const dotMotia = path.join(baseDir, motiaFileStoragePath);
27
24
  const appConfig = await loadMotiaConfig(baseDir);
28
- const redisClient = await instanceRedisMemoryServer(dotMotia);
29
25
  const adapters = {
30
26
  eventAdapter: appConfig.adapters?.events || new DefaultQueueEventAdapter(),
31
27
  cronAdapter: appConfig.adapters?.cron || new DefaultCronAdapter(),
32
- streamAdapter: appConfig.adapters?.streams || new RedisStreamAdapterManager(redisClient),
28
+ streamAdapter: appConfig.adapters?.streams || new FileStreamAdapterManager(baseDir),
33
29
  };
34
30
  const lockedData = await generateLockedData({
35
31
  projectDir: baseDir,
36
32
  streamAdapter: adapters.streamAdapter,
37
- redisClient,
38
33
  });
39
- const state = appConfig.adapters?.state || new RedisStateAdapter(redisClient);
34
+ const state = appConfig.adapters?.state || createStateAdapter({ adapter: 'default', filePath: dotMotia });
40
35
  const config = { isVerbose, isDev: false, version };
41
36
  const motiaServer = createServer(lockedData, state, config, adapters, appConfig.app);
42
37
  const plugins = await processPlugins(motiaServer);
@@ -52,14 +47,13 @@ export const start = async (port, hostname, disableVerbose, motiaFileStorageDir)
52
47
  motiaServer.server.listen(port, hostname);
53
48
  console.log('🚀 Server ready and listening on port', port);
54
49
  console.log(`🔗 Open http://${hostname}:${port}${workbenchBase} to open workbench 🛠️`);
50
+ // 6) Gracefully shut down on SIGTERM
55
51
  process.on('SIGTERM', async () => {
56
52
  motiaServer.server.close();
57
- await stopRedisMemoryServer();
58
53
  process.exit(0);
59
54
  });
60
55
  process.on('SIGINT', async () => {
61
56
  motiaServer.server.close();
62
- await stopRedisMemoryServer();
63
57
  process.exit(0);
64
58
  });
65
59
  };
@@ -1,11 +1,9 @@
1
1
  import { LockedData, type Step, type StreamAdapterManager } from '@motiadev/core';
2
- import type { RedisClientType } from 'redis';
3
2
  export declare const getStepFiles: (projectDir: string) => string[];
4
3
  export declare const getStreamFiles: (projectDir: string) => string[];
5
4
  export declare const collectFlows: (projectDir: string, lockedData: LockedData) => Promise<Step[]>;
6
5
  export declare const generateLockedData: (config: {
7
6
  projectDir: string;
8
7
  streamAdapter: StreamAdapterManager;
9
- redisClient: RedisClientType;
10
8
  printerType?: "disabled" | "default";
11
9
  }) => Promise<LockedData>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "motia",
3
3
  "description": "Build production-grade backends with a single primitive. APIs, background jobs, Queues, Workflows, and AI agents - unified in one system with built-in State management, Streaming, and Observability.",
4
- "version": "0.11.1-beta.156-879726",
4
+ "version": "0.11.1-beta.156-960492",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -44,15 +44,11 @@
44
44
  "inquirer": "^8.2.5",
45
45
  "node-cron": "^3.0.3",
46
46
  "python-ast": "^0.1.0",
47
- "redis": "^5.9.0",
48
- "redis-memory-server": "^0.14.0",
49
47
  "table": "^6.9.0",
50
48
  "ts-node": "^10.9.2",
51
- "@motiadev/adapter-redis-state": "0.11.1-beta.156-879726",
52
- "@motiadev/core": "0.11.1-beta.156-879726",
53
- "@motiadev/stream-client-node": "0.11.1-beta.156-879726",
54
- "@motiadev/workbench": "0.11.1-beta.156-879726",
55
- "@motiadev/adapter-redis-streams": "0.11.1-beta.156-879726"
49
+ "@motiadev/stream-client-node": "0.11.1-beta.156-960492",
50
+ "@motiadev/core": "0.11.1-beta.156-960492",
51
+ "@motiadev/workbench": "0.11.1-beta.156-960492"
56
52
  },
57
53
  "devDependencies": {
58
54
  "@amplitude/analytics-types": "^2.9.2",
@@ -1 +0,0 @@
1
- export {};
@@ -1,175 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const fs_1 = require("fs");
4
- const redis_1 = require("redis");
5
- const redis_memory_server_1 = require("redis-memory-server");
6
- const redis_memory_manager_1 = require("../redis-memory-manager");
7
- jest.mock('fs');
8
- jest.mock('redis');
9
- jest.mock('redis-memory-server');
10
- const mockMkdirSync = fs_1.mkdirSync;
11
- const mockCreateClient = redis_1.createClient;
12
- const mockRedisMemoryServer = redis_memory_server_1.RedisMemoryServer;
13
- describe('redis-memory-manager', () => {
14
- let mockRedisClient;
15
- let mockServerInstance;
16
- const originalEnv = process.env;
17
- beforeEach(() => {
18
- jest.clearAllMocks();
19
- process.env = { ...originalEnv };
20
- mockRedisClient = {
21
- connect: jest.fn().mockResolvedValue(undefined),
22
- quit: jest.fn().mockResolvedValue(undefined),
23
- isOpen: true,
24
- on: jest.fn(),
25
- };
26
- mockServerInstance = {
27
- getHost: jest.fn().mockResolvedValue('127.0.0.1'),
28
- getPort: jest.fn().mockResolvedValue(6379),
29
- stop: jest.fn().mockResolvedValue(undefined),
30
- };
31
- mockCreateClient.mockReturnValue(mockRedisClient);
32
- mockRedisMemoryServer.mockImplementation(() => mockServerInstance);
33
- });
34
- afterEach(async () => {
35
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
36
- process.env = originalEnv;
37
- });
38
- describe('instanceRedisMemoryServer', () => {
39
- it('should start Redis server and return client', async () => {
40
- const baseDir = '/test/dir';
41
- const client = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
42
- expect(mockMkdirSync).toHaveBeenCalledWith(baseDir, { recursive: true });
43
- expect(mockRedisMemoryServer).toHaveBeenCalledWith({
44
- instance: {
45
- ip: '127.0.0.1',
46
- args: ['--appendonly', 'yes', '--save', '900 1', '--save', '300 10', '--save', '60 100', '--dir', baseDir],
47
- },
48
- autoStart: true,
49
- });
50
- expect(mockServerInstance.getHost).toHaveBeenCalled();
51
- expect(mockServerInstance.getPort).toHaveBeenCalled();
52
- expect(mockCreateClient).toHaveBeenCalledWith({
53
- socket: {
54
- host: '127.0.0.1',
55
- port: 6379,
56
- reconnectStrategy: expect.any(Function),
57
- connectTimeout: 10000,
58
- },
59
- });
60
- expect(mockRedisClient.connect).toHaveBeenCalled();
61
- expect(client).toBe(mockRedisClient);
62
- });
63
- it('should use custom host from environment variable', async () => {
64
- process.env.MOTIA_REDIS_HOST = '192.168.1.1';
65
- const baseDir = '/test/dir';
66
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, false);
67
- expect(mockRedisMemoryServer).toHaveBeenCalledWith({
68
- instance: expect.objectContaining({
69
- ip: '192.168.1.1',
70
- }),
71
- autoStart: false,
72
- });
73
- });
74
- it('should use custom port from environment variable', async () => {
75
- process.env.MOTIA_REDIS_PORT = '6380';
76
- const baseDir = '/test/dir';
77
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
78
- expect(mockRedisMemoryServer).toHaveBeenCalledWith({
79
- instance: expect.objectContaining({
80
- port: 6380,
81
- }),
82
- autoStart: true,
83
- });
84
- });
85
- it('should return existing client if already running', async () => {
86
- const baseDir = '/test/dir';
87
- const client1 = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
88
- const client2 = await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, false);
89
- expect(client1).toBe(client2);
90
- expect(mockRedisMemoryServer).toHaveBeenCalledTimes(1);
91
- expect(mockCreateClient).toHaveBeenCalledTimes(1);
92
- });
93
- it('should set up error handler on client', async () => {
94
- const baseDir = '/test/dir';
95
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
96
- expect(mockRedisClient.on).toHaveBeenCalledWith('error', expect.any(Function));
97
- });
98
- it('should handle connection errors', async () => {
99
- const baseDir = '/test/dir';
100
- const error = new Error('Connection failed');
101
- mockRedisClient.connect.mockRejectedValue(error);
102
- await expect((0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true)).rejects.toThrow('Connection failed');
103
- });
104
- it('should handle server start errors', async () => {
105
- const baseDir = '/test/dir';
106
- const error = new Error('Server start failed');
107
- mockServerInstance.getHost.mockRejectedValue(error);
108
- await expect((0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true)).rejects.toThrow('Server start failed');
109
- });
110
- it('should implement reconnect strategy correctly', async () => {
111
- const baseDir = '/test/dir';
112
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
113
- const callArgs = mockCreateClient.mock.calls[0];
114
- expect(callArgs).toBeDefined();
115
- const socketConfig = callArgs?.[0]?.socket;
116
- expect(socketConfig).toBeDefined();
117
- const reconnectStrategy = socketConfig?.reconnectStrategy;
118
- expect(reconnectStrategy).toBeDefined();
119
- expect(typeof reconnectStrategy).toBe('function');
120
- if (reconnectStrategy && typeof reconnectStrategy === 'function') {
121
- const mockError = new Error('test');
122
- expect(reconnectStrategy(5, mockError)).toBe(500);
123
- expect(reconnectStrategy(10, mockError)).toBe(1000);
124
- expect(reconnectStrategy(11, mockError)).toBeInstanceOf(Error);
125
- expect(reconnectStrategy(11, mockError).message).toBe('Redis connection retry limit exceeded');
126
- expect(reconnectStrategy(15, mockError)).toBeInstanceOf(Error);
127
- expect(reconnectStrategy(20, mockError)).toBeInstanceOf(Error);
128
- expect(reconnectStrategy(30, mockError)).toBeInstanceOf(Error);
129
- expect(reconnectStrategy(50, mockError)).toBeInstanceOf(Error);
130
- }
131
- });
132
- });
133
- describe('stopRedisMemoryServer', () => {
134
- it('should stop Redis server and close client', async () => {
135
- const baseDir = '/test/dir';
136
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
137
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
138
- expect(mockRedisClient.quit).toHaveBeenCalled();
139
- expect(mockServerInstance.stop).toHaveBeenCalled();
140
- });
141
- it('should handle client close errors gracefully', async () => {
142
- const baseDir = '/test/dir';
143
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
144
- const error = new Error('Close failed');
145
- mockRedisClient.quit.mockRejectedValue(error);
146
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
147
- expect(mockRedisClient.quit).toHaveBeenCalled();
148
- expect(mockServerInstance.stop).toHaveBeenCalled();
149
- });
150
- it('should handle server stop errors gracefully', async () => {
151
- const baseDir = '/test/dir';
152
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
153
- const error = new Error('Stop failed');
154
- mockServerInstance.stop.mockRejectedValue(error);
155
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
156
- expect(mockRedisClient.quit).toHaveBeenCalled();
157
- expect(mockServerInstance.stop).toHaveBeenCalled();
158
- });
159
- it('should not throw if client is not open', async () => {
160
- const baseDir = '/test/dir';
161
- await (0, redis_memory_manager_1.instanceRedisMemoryServer)(baseDir, true);
162
- Object.defineProperty(mockRedisClient, 'isOpen', {
163
- value: false,
164
- writable: true,
165
- configurable: true,
166
- });
167
- await expect((0, redis_memory_manager_1.stopRedisMemoryServer)()).resolves.not.toThrow();
168
- });
169
- it('should do nothing if server is not running', async () => {
170
- await (0, redis_memory_manager_1.stopRedisMemoryServer)();
171
- expect(mockRedisClient.quit).not.toHaveBeenCalled();
172
- expect(mockServerInstance.stop).not.toHaveBeenCalled();
173
- });
174
- });
175
- });
@@ -1,51 +0,0 @@
1
- export interface MockRedisClient {
2
- connect: jest.Mock<Promise<void>>;
3
- quit: jest.Mock<Promise<void>>;
4
- disconnect: jest.Mock<Promise<void>>;
5
- isOpen: boolean;
6
- on: jest.Mock;
7
- get: jest.Mock<Promise<string | null>>;
8
- set: jest.Mock<Promise<string | null>>;
9
- del: jest.Mock<Promise<number>>;
10
- exists: jest.Mock<Promise<number>>;
11
- keys: jest.Mock<Promise<string[]>>;
12
- flushAll: jest.Mock<Promise<string>>;
13
- ping: jest.Mock<Promise<string>>;
14
- xAdd: jest.Mock<Promise<string>>;
15
- xRead: jest.Mock<Promise<unknown[]>>;
16
- xReadGroup: jest.Mock<Promise<unknown[]>>;
17
- xGroupCreate: jest.Mock<Promise<string>>;
18
- xAck: jest.Mock<Promise<number>>;
19
- hGet: jest.Mock<Promise<string | null>>;
20
- hSet: jest.Mock<Promise<number>>;
21
- hGetAll: jest.Mock<Promise<Record<string, string>>>;
22
- hDel: jest.Mock<Promise<number>>;
23
- hExists: jest.Mock<Promise<number>>;
24
- expire: jest.Mock<Promise<number>>;
25
- ttl: jest.Mock<Promise<number>>;
26
- publish: jest.Mock<Promise<number>>;
27
- [key: string]: unknown;
28
- }
29
- export interface RedisTestHelperOptions {
30
- autoConnect?: boolean;
31
- isOpen?: boolean;
32
- }
33
- export declare function createMockRedisClient(options?: RedisTestHelperOptions): MockRedisClient;
34
- export declare function resetMockRedisClient(client: MockRedisClient): void;
35
- export declare function setupRedisTestHelper(): {
36
- mockClient: MockRedisClient;
37
- reset: () => void;
38
- };
39
- export declare class RedisTestHelper {
40
- private client;
41
- constructor(options?: RedisTestHelperOptions);
42
- getClient(): MockRedisClient;
43
- reset(): void;
44
- mockGet(key: string, value: string | null): void;
45
- mockSet(_key: string, _value: string): void;
46
- mockExists(key: string, exists: boolean): void;
47
- mockKeys(_pattern: string, keys: string[]): void;
48
- mockConnectError(error: Error): void;
49
- mockQuitError(error: Error): void;
50
- setConnectionState(isOpen: boolean): void;
51
- }