@hotmeshio/hotmesh 0.4.0 → 0.4.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.
Files changed (283) hide show
  1. package/build/modules/enums.d.ts +110 -0
  2. package/build/modules/enums.js +134 -0
  3. package/build/modules/errors.d.ts +124 -0
  4. package/build/modules/errors.js +191 -0
  5. package/build/modules/key.d.ts +66 -0
  6. package/build/modules/key.js +190 -0
  7. package/build/modules/storage.d.ts +3 -0
  8. package/build/modules/storage.js +5 -0
  9. package/build/modules/utils.d.ts +119 -0
  10. package/build/modules/utils.js +374 -0
  11. package/build/package.json +1 -1
  12. package/build/services/activities/activity.d.ts +104 -0
  13. package/build/services/activities/activity.js +549 -0
  14. package/build/services/activities/await.d.ts +12 -0
  15. package/build/services/activities/await.js +114 -0
  16. package/build/services/activities/cycle.d.ts +19 -0
  17. package/build/services/activities/cycle.js +112 -0
  18. package/build/services/activities/hook.d.ts +27 -0
  19. package/build/services/activities/hook.js +168 -0
  20. package/build/services/activities/index.d.ts +19 -0
  21. package/build/services/activities/index.js +20 -0
  22. package/build/services/activities/interrupt.d.ts +16 -0
  23. package/build/services/activities/interrupt.js +158 -0
  24. package/build/services/activities/signal.d.ts +20 -0
  25. package/build/services/activities/signal.js +134 -0
  26. package/build/services/activities/trigger.d.ts +37 -0
  27. package/build/services/activities/trigger.js +246 -0
  28. package/build/services/activities/worker.d.ts +12 -0
  29. package/build/services/activities/worker.js +106 -0
  30. package/build/services/collator/index.d.ts +111 -0
  31. package/build/services/collator/index.js +293 -0
  32. package/build/services/compiler/deployer.d.ts +40 -0
  33. package/build/services/compiler/deployer.js +488 -0
  34. package/build/services/compiler/index.d.ts +32 -0
  35. package/build/services/compiler/index.js +112 -0
  36. package/build/services/compiler/validator.d.ts +34 -0
  37. package/build/services/compiler/validator.js +147 -0
  38. package/build/services/connector/factory.d.ts +22 -0
  39. package/build/services/connector/factory.js +99 -0
  40. package/build/services/connector/index.d.ts +30 -0
  41. package/build/services/connector/index.js +54 -0
  42. package/build/services/connector/providers/ioredis.d.ts +9 -0
  43. package/build/services/connector/providers/ioredis.js +26 -0
  44. package/build/services/connector/providers/nats.d.ts +9 -0
  45. package/build/services/connector/providers/nats.js +34 -0
  46. package/build/services/connector/providers/postgres.d.ts +20 -0
  47. package/build/services/connector/providers/postgres.js +102 -0
  48. package/build/services/connector/providers/redis.d.ts +9 -0
  49. package/build/services/connector/providers/redis.js +38 -0
  50. package/build/services/engine/index.d.ts +264 -0
  51. package/build/services/engine/index.js +761 -0
  52. package/build/services/exporter/index.d.ts +44 -0
  53. package/build/services/exporter/index.js +126 -0
  54. package/build/services/hotmesh/index.d.ts +483 -0
  55. package/build/services/hotmesh/index.js +622 -0
  56. package/build/services/logger/index.d.ts +16 -0
  57. package/build/services/logger/index.js +54 -0
  58. package/build/services/mapper/index.d.ts +28 -0
  59. package/build/services/mapper/index.js +81 -0
  60. package/build/services/memflow/client.d.ts +108 -0
  61. package/build/services/memflow/client.js +372 -0
  62. package/build/services/memflow/connection.d.ts +23 -0
  63. package/build/services/memflow/connection.js +33 -0
  64. package/build/services/memflow/context.d.ts +143 -0
  65. package/build/services/memflow/context.js +299 -0
  66. package/build/services/memflow/exporter.d.ts +51 -0
  67. package/build/services/memflow/exporter.js +215 -0
  68. package/build/services/memflow/handle.d.ts +90 -0
  69. package/build/services/memflow/handle.js +176 -0
  70. package/build/services/memflow/index.d.ts +116 -0
  71. package/build/services/memflow/index.js +122 -0
  72. package/build/services/memflow/schemas/factory.d.ts +29 -0
  73. package/build/services/memflow/schemas/factory.js +2492 -0
  74. package/build/services/memflow/search.d.ts +142 -0
  75. package/build/services/memflow/search.js +320 -0
  76. package/build/services/memflow/worker.d.ts +124 -0
  77. package/build/services/memflow/worker.js +514 -0
  78. package/build/services/memflow/workflow/all.d.ts +7 -0
  79. package/build/services/memflow/workflow/all.js +15 -0
  80. package/build/services/memflow/workflow/common.d.ts +20 -0
  81. package/build/services/memflow/workflow/common.js +47 -0
  82. package/build/services/memflow/workflow/context.d.ts +6 -0
  83. package/build/services/memflow/workflow/context.js +45 -0
  84. package/build/services/memflow/workflow/contextMethods.d.ts +14 -0
  85. package/build/services/memflow/workflow/contextMethods.js +33 -0
  86. package/build/services/memflow/workflow/didRun.d.ts +7 -0
  87. package/build/services/memflow/workflow/didRun.js +22 -0
  88. package/build/services/memflow/workflow/emit.d.ts +11 -0
  89. package/build/services/memflow/workflow/emit.js +29 -0
  90. package/build/services/memflow/workflow/enrich.d.ts +9 -0
  91. package/build/services/memflow/workflow/enrich.js +17 -0
  92. package/build/services/memflow/workflow/execChild.d.ts +18 -0
  93. package/build/services/memflow/workflow/execChild.js +102 -0
  94. package/build/services/memflow/workflow/execHook.d.ts +65 -0
  95. package/build/services/memflow/workflow/execHook.js +73 -0
  96. package/build/services/memflow/workflow/hook.d.ts +9 -0
  97. package/build/services/memflow/workflow/hook.js +56 -0
  98. package/build/services/memflow/workflow/index.d.ts +74 -0
  99. package/build/services/memflow/workflow/index.js +87 -0
  100. package/build/services/memflow/workflow/interrupt.d.ts +9 -0
  101. package/build/services/memflow/workflow/interrupt.js +24 -0
  102. package/build/services/memflow/workflow/isSideEffectAllowed.d.ts +10 -0
  103. package/build/services/memflow/workflow/isSideEffectAllowed.js +33 -0
  104. package/build/services/memflow/workflow/proxyActivities.d.ts +20 -0
  105. package/build/services/memflow/workflow/proxyActivities.js +97 -0
  106. package/build/services/memflow/workflow/random.d.ts +6 -0
  107. package/build/services/memflow/workflow/random.js +16 -0
  108. package/build/services/memflow/workflow/searchMethods.d.ts +6 -0
  109. package/build/services/memflow/workflow/searchMethods.js +25 -0
  110. package/build/services/memflow/workflow/signal.d.ts +7 -0
  111. package/build/services/memflow/workflow/signal.js +28 -0
  112. package/build/services/memflow/workflow/sleepFor.d.ts +8 -0
  113. package/build/services/memflow/workflow/sleepFor.js +35 -0
  114. package/build/services/memflow/workflow/trace.d.ts +14 -0
  115. package/build/services/memflow/workflow/trace.js +33 -0
  116. package/build/services/memflow/workflow/waitFor.d.ts +8 -0
  117. package/build/services/memflow/workflow/waitFor.js +35 -0
  118. package/build/services/meshcall/index.d.ts +194 -0
  119. package/build/services/meshcall/index.js +452 -0
  120. package/build/services/meshcall/schemas/factory.d.ts +9 -0
  121. package/build/services/meshcall/schemas/factory.js +189 -0
  122. package/build/services/meshdata/index.d.ts +795 -0
  123. package/build/services/meshdata/index.js +1235 -0
  124. package/build/services/meshos/index.d.ts +293 -0
  125. package/build/services/meshos/index.js +547 -0
  126. package/build/services/pipe/functions/array.d.ts +17 -0
  127. package/build/services/pipe/functions/array.js +74 -0
  128. package/build/services/pipe/functions/bitwise.d.ts +9 -0
  129. package/build/services/pipe/functions/bitwise.js +24 -0
  130. package/build/services/pipe/functions/conditional.d.ts +13 -0
  131. package/build/services/pipe/functions/conditional.js +36 -0
  132. package/build/services/pipe/functions/cron.d.ts +12 -0
  133. package/build/services/pipe/functions/cron.js +40 -0
  134. package/build/services/pipe/functions/date.d.ts +58 -0
  135. package/build/services/pipe/functions/date.js +171 -0
  136. package/build/services/pipe/functions/index.d.ts +29 -0
  137. package/build/services/pipe/functions/index.js +30 -0
  138. package/build/services/pipe/functions/json.d.ts +5 -0
  139. package/build/services/pipe/functions/json.js +12 -0
  140. package/build/services/pipe/functions/logical.d.ts +5 -0
  141. package/build/services/pipe/functions/logical.js +12 -0
  142. package/build/services/pipe/functions/math.d.ts +42 -0
  143. package/build/services/pipe/functions/math.js +184 -0
  144. package/build/services/pipe/functions/number.d.ts +21 -0
  145. package/build/services/pipe/functions/number.js +60 -0
  146. package/build/services/pipe/functions/object.d.ts +25 -0
  147. package/build/services/pipe/functions/object.js +81 -0
  148. package/build/services/pipe/functions/string.d.ts +23 -0
  149. package/build/services/pipe/functions/string.js +69 -0
  150. package/build/services/pipe/functions/symbol.d.ts +12 -0
  151. package/build/services/pipe/functions/symbol.js +33 -0
  152. package/build/services/pipe/functions/unary.d.ts +7 -0
  153. package/build/services/pipe/functions/unary.js +18 -0
  154. package/build/services/pipe/index.d.ts +48 -0
  155. package/build/services/pipe/index.js +242 -0
  156. package/build/services/quorum/index.d.ts +90 -0
  157. package/build/services/quorum/index.js +263 -0
  158. package/build/services/reporter/index.d.ts +50 -0
  159. package/build/services/reporter/index.js +348 -0
  160. package/build/services/router/config/index.d.ts +11 -0
  161. package/build/services/router/config/index.js +36 -0
  162. package/build/services/router/consumption/index.d.ts +34 -0
  163. package/build/services/router/consumption/index.js +395 -0
  164. package/build/services/router/error-handling/index.d.ts +8 -0
  165. package/build/services/router/error-handling/index.js +98 -0
  166. package/build/services/router/index.d.ts +57 -0
  167. package/build/services/router/index.js +121 -0
  168. package/build/services/router/lifecycle/index.d.ts +27 -0
  169. package/build/services/router/lifecycle/index.js +80 -0
  170. package/build/services/router/telemetry/index.d.ts +11 -0
  171. package/build/services/router/telemetry/index.js +32 -0
  172. package/build/services/router/throttling/index.d.ts +23 -0
  173. package/build/services/router/throttling/index.js +76 -0
  174. package/build/services/search/factory.d.ts +7 -0
  175. package/build/services/search/factory.js +24 -0
  176. package/build/services/search/index.d.ts +23 -0
  177. package/build/services/search/index.js +10 -0
  178. package/build/services/search/providers/postgres/postgres.d.ts +25 -0
  179. package/build/services/search/providers/postgres/postgres.js +149 -0
  180. package/build/services/search/providers/redis/ioredis.d.ts +19 -0
  181. package/build/services/search/providers/redis/ioredis.js +121 -0
  182. package/build/services/search/providers/redis/redis.d.ts +19 -0
  183. package/build/services/search/providers/redis/redis.js +134 -0
  184. package/build/services/serializer/index.d.ts +42 -0
  185. package/build/services/serializer/index.js +282 -0
  186. package/build/services/store/cache.d.ts +67 -0
  187. package/build/services/store/cache.js +128 -0
  188. package/build/services/store/factory.d.ts +8 -0
  189. package/build/services/store/factory.js +24 -0
  190. package/build/services/store/index.d.ts +89 -0
  191. package/build/services/store/index.js +9 -0
  192. package/build/services/store/providers/postgres/kvsql.d.ts +168 -0
  193. package/build/services/store/providers/postgres/kvsql.js +198 -0
  194. package/build/services/store/providers/postgres/kvtables.d.ts +20 -0
  195. package/build/services/store/providers/postgres/kvtables.js +441 -0
  196. package/build/services/store/providers/postgres/kvtransaction.d.ts +36 -0
  197. package/build/services/store/providers/postgres/kvtransaction.js +248 -0
  198. package/build/services/store/providers/postgres/kvtypes/hash.d.ts +60 -0
  199. package/build/services/store/providers/postgres/kvtypes/hash.js +1287 -0
  200. package/build/services/store/providers/postgres/kvtypes/list.d.ts +33 -0
  201. package/build/services/store/providers/postgres/kvtypes/list.js +194 -0
  202. package/build/services/store/providers/postgres/kvtypes/string.d.ts +20 -0
  203. package/build/services/store/providers/postgres/kvtypes/string.js +115 -0
  204. package/build/services/store/providers/postgres/kvtypes/zset.d.ts +41 -0
  205. package/build/services/store/providers/postgres/kvtypes/zset.js +214 -0
  206. package/build/services/store/providers/postgres/postgres.d.ts +145 -0
  207. package/build/services/store/providers/postgres/postgres.js +1036 -0
  208. package/build/services/store/providers/redis/_base.d.ts +137 -0
  209. package/build/services/store/providers/redis/_base.js +980 -0
  210. package/build/services/store/providers/redis/ioredis.d.ts +20 -0
  211. package/build/services/store/providers/redis/ioredis.js +180 -0
  212. package/build/services/store/providers/redis/redis.d.ts +18 -0
  213. package/build/services/store/providers/redis/redis.js +199 -0
  214. package/build/services/store/providers/store-initializable.d.ts +5 -0
  215. package/build/services/store/providers/store-initializable.js +2 -0
  216. package/build/services/stream/factory.d.ts +8 -0
  217. package/build/services/stream/factory.js +37 -0
  218. package/build/services/stream/index.d.ts +69 -0
  219. package/build/services/stream/index.js +11 -0
  220. package/build/services/stream/providers/nats/nats.d.ts +60 -0
  221. package/build/services/stream/providers/nats/nats.js +225 -0
  222. package/build/services/stream/providers/postgres/kvtables.d.ts +3 -0
  223. package/build/services/stream/providers/postgres/kvtables.js +146 -0
  224. package/build/services/stream/providers/postgres/postgres.d.ts +107 -0
  225. package/build/services/stream/providers/postgres/postgres.js +519 -0
  226. package/build/services/stream/providers/redis/ioredis.d.ts +61 -0
  227. package/build/services/stream/providers/redis/ioredis.js +272 -0
  228. package/build/services/stream/providers/redis/redis.d.ts +61 -0
  229. package/build/services/stream/providers/redis/redis.js +305 -0
  230. package/build/services/stream/providers/stream-initializable.d.ts +4 -0
  231. package/build/services/stream/providers/stream-initializable.js +2 -0
  232. package/build/services/sub/factory.d.ts +7 -0
  233. package/build/services/sub/factory.js +29 -0
  234. package/build/services/sub/index.d.ts +22 -0
  235. package/build/services/sub/index.js +10 -0
  236. package/build/services/sub/providers/nats/nats.d.ts +19 -0
  237. package/build/services/sub/providers/nats/nats.js +105 -0
  238. package/build/services/sub/providers/postgres/postgres.d.ts +19 -0
  239. package/build/services/sub/providers/postgres/postgres.js +92 -0
  240. package/build/services/sub/providers/redis/ioredis.d.ts +17 -0
  241. package/build/services/sub/providers/redis/ioredis.js +81 -0
  242. package/build/services/sub/providers/redis/redis.d.ts +17 -0
  243. package/build/services/sub/providers/redis/redis.js +72 -0
  244. package/build/services/task/index.d.ts +36 -0
  245. package/build/services/task/index.js +206 -0
  246. package/build/services/telemetry/index.d.ts +52 -0
  247. package/build/services/telemetry/index.js +306 -0
  248. package/build/services/worker/index.d.ts +77 -0
  249. package/build/services/worker/index.js +197 -0
  250. package/package.json +1 -1
  251. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  252. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  253. package/typedoc.json +0 -47
  254. package/types/activity.ts +0 -268
  255. package/types/app.ts +0 -20
  256. package/types/async.ts +0 -6
  257. package/types/cache.ts +0 -1
  258. package/types/collator.ts +0 -9
  259. package/types/error.ts +0 -56
  260. package/types/exporter.ts +0 -102
  261. package/types/hook.ts +0 -44
  262. package/types/hotmesh.ts +0 -314
  263. package/types/index.ts +0 -306
  264. package/types/job.ts +0 -233
  265. package/types/logger.ts +0 -8
  266. package/types/manifest.ts +0 -70
  267. package/types/map.ts +0 -5
  268. package/types/memflow.ts +0 -645
  269. package/types/meshcall.ts +0 -235
  270. package/types/meshdata.ts +0 -278
  271. package/types/ms.d.ts +0 -7
  272. package/types/nats.ts +0 -270
  273. package/types/pipe.ts +0 -90
  274. package/types/postgres.ts +0 -114
  275. package/types/provider.ts +0 -161
  276. package/types/quorum.ts +0 -167
  277. package/types/redis.ts +0 -404
  278. package/types/serializer.ts +0 -40
  279. package/types/stats.ts +0 -117
  280. package/types/stream.ts +0 -231
  281. package/types/task.ts +0 -7
  282. package/types/telemetry.ts +0 -16
  283. package/types/transition.ts +0 -20
@@ -0,0 +1,441 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KVTables = void 0;
4
+ const enums_1 = require("../../../../modules/enums");
5
+ const utils_1 = require("../../../../modules/utils");
6
+ const KVTables = (context) => ({
7
+ /**
8
+ * Deploys the necessary tables with the specified naming strategy.
9
+ * @param appName - The name of the application.
10
+ */
11
+ async deploy(appName) {
12
+ const transactionClient = context.pgClient;
13
+ let client;
14
+ let releaseClient = false;
15
+ if (transactionClient?.totalCount !== undefined &&
16
+ transactionClient?.idleCount !== undefined) {
17
+ // It's a Pool, need to acquire a client
18
+ client = await transactionClient.connect();
19
+ releaseClient = true;
20
+ }
21
+ else {
22
+ // Assume it's a connected Client
23
+ client = transactionClient;
24
+ }
25
+ try {
26
+ // Acquire advisory lock
27
+ const lockId = this.getAdvisoryLockId(appName);
28
+ const lockResult = await client.query('SELECT pg_try_advisory_lock($1) AS locked', [lockId]);
29
+ if (lockResult.rows[0].locked) {
30
+ // Begin transaction
31
+ await client.query('BEGIN');
32
+ // Check and create tables
33
+ const tablesExist = await this.checkIfTablesExist(client, appName);
34
+ if (!tablesExist) {
35
+ await this.createTables(client, appName);
36
+ }
37
+ // Commit transaction
38
+ await client.query('COMMIT');
39
+ // Release the lock
40
+ await client.query('SELECT pg_advisory_unlock($1)', [lockId]);
41
+ }
42
+ else {
43
+ // Release the client before waiting
44
+ if (releaseClient && client.release) {
45
+ await client.release();
46
+ releaseClient = false;
47
+ }
48
+ // Wait for the deploy process to complete
49
+ await this.waitForTablesCreation(lockId, appName);
50
+ }
51
+ }
52
+ catch (error) {
53
+ console.error(error);
54
+ context.logger.error('Error deploying tables', { error });
55
+ throw error;
56
+ }
57
+ finally {
58
+ if (releaseClient && client.release) {
59
+ await client.release();
60
+ }
61
+ }
62
+ },
63
+ getAdvisoryLockId(appName) {
64
+ return this.hashStringToInt(appName);
65
+ },
66
+ hashStringToInt(str) {
67
+ let hash = 0;
68
+ for (let i = 0; i < str.length; i++) {
69
+ hash = (hash << 5) - hash + str.charCodeAt(i);
70
+ hash |= 0; // Convert to 32-bit integer
71
+ }
72
+ return Math.abs(hash);
73
+ },
74
+ async waitForTablesCreation(lockId, appName) {
75
+ let retries = 0;
76
+ const maxRetries = Math.round(enums_1.HMSH_DEPLOYMENT_DELAY / enums_1.HMSH_DEPLOYMENT_PAUSE);
77
+ while (retries < maxRetries) {
78
+ await (0, utils_1.sleepFor)(enums_1.HMSH_DEPLOYMENT_PAUSE);
79
+ let client;
80
+ let releaseClient = false;
81
+ const transactionClient = context.pgClient;
82
+ if (transactionClient?.totalCount !== undefined &&
83
+ transactionClient?.idleCount !== undefined) {
84
+ // It's a Pool, need to acquire a client
85
+ client = await transactionClient.connect();
86
+ releaseClient = true;
87
+ }
88
+ else {
89
+ // Assume it's a connected Client
90
+ client = transactionClient;
91
+ }
92
+ try {
93
+ const lockCheck = await client.query("SELECT NOT EXISTS (SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND objid = $1::bigint) AS unlocked", [lockId]);
94
+ if (lockCheck.rows[0].unlocked) {
95
+ // Lock has been released, tables should exist now
96
+ const tablesExist = await this.checkIfTablesExist(client, appName);
97
+ if (tablesExist) {
98
+ return;
99
+ }
100
+ }
101
+ }
102
+ finally {
103
+ if (releaseClient && client.release) {
104
+ await client.release();
105
+ }
106
+ }
107
+ retries++;
108
+ }
109
+ console.error('table-create-timeout', { appName });
110
+ throw new Error('Timeout waiting for table creation');
111
+ },
112
+ async checkIfTablesExist(client, appName) {
113
+ const tableNames = this.getTableNames(appName);
114
+ const checkTablePromises = tableNames.map((tableName) => client.query(`SELECT to_regclass('${tableName}') AS table`));
115
+ const results = await Promise.all(checkTablePromises);
116
+ return results.every((res) => res.rows[0].table !== null);
117
+ },
118
+ async createTables(client, appName) {
119
+ try {
120
+ await client.query('BEGIN');
121
+ const schemaName = context.storeClient.safeName(appName);
122
+ await client.query(`CREATE SCHEMA IF NOT EXISTS ${schemaName};`);
123
+ const tableDefinitions = this.getTableDefinitions(appName);
124
+ for (const tableDef of tableDefinitions) {
125
+ const fullTableName = `${tableDef.schema}.${tableDef.name}`;
126
+ switch (tableDef.type) {
127
+ case 'string':
128
+ await client.query(`
129
+ CREATE TABLE IF NOT EXISTS ${fullTableName} (
130
+ key TEXT PRIMARY KEY,
131
+ value TEXT,
132
+ expiry TIMESTAMP WITH TIME ZONE
133
+ );
134
+ `);
135
+ break;
136
+ case 'hash':
137
+ await client.query(`
138
+ CREATE TABLE IF NOT EXISTS ${fullTableName} (
139
+ key TEXT NOT NULL,
140
+ field TEXT NOT NULL,
141
+ value TEXT,
142
+ expiry TIMESTAMP WITH TIME ZONE,
143
+ PRIMARY KEY (key, field)
144
+ );
145
+ `);
146
+ break;
147
+ case 'jobhash':
148
+ // Create the enum type in the schema
149
+ await client.query(`
150
+ DO $$
151
+ BEGIN
152
+ IF NOT EXISTS (
153
+ SELECT 1 FROM pg_type t
154
+ JOIN pg_namespace n ON n.oid = t.typnamespace
155
+ WHERE t.typname = 'type_enum' AND n.nspname = '${schemaName}'
156
+ ) THEN
157
+ CREATE TYPE ${schemaName}.type_enum AS ENUM ('jmark', 'hmark', 'status', 'jdata', 'adata', 'udata', 'other');
158
+ END IF;
159
+ END$$;
160
+ `);
161
+ // Create the main jobs table with partitioning on id
162
+ await client.query(`
163
+ CREATE TABLE IF NOT EXISTS ${fullTableName} (
164
+ id UUID DEFAULT gen_random_uuid(),
165
+ key TEXT NOT NULL,
166
+ entity TEXT,
167
+ status INTEGER NOT NULL,
168
+ context JSONB DEFAULT '{}',
169
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
170
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
171
+ expired_at TIMESTAMP WITH TIME ZONE,
172
+ is_live BOOLEAN DEFAULT TRUE,
173
+ PRIMARY KEY (id)
174
+ ) PARTITION BY HASH (id);
175
+ `);
176
+ // Create GIN index for full JSONB search
177
+ await client.query(`
178
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_context_gin
179
+ ON ${fullTableName} USING GIN (context);
180
+ `);
181
+ // Create partitions using a DO block
182
+ await client.query(`
183
+ DO $$
184
+ BEGIN
185
+ FOR i IN 0..7 LOOP
186
+ EXECUTE format(
187
+ 'CREATE TABLE IF NOT EXISTS ${fullTableName}_part_%s PARTITION OF ${fullTableName}
188
+ FOR VALUES WITH (modulus 8, remainder %s)',
189
+ i, i
190
+ );
191
+ END LOOP;
192
+ END$$;
193
+ `);
194
+ // Create optimized indexes
195
+ await client.query(`
196
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_key_expired_at
197
+ ON ${fullTableName} (key, expired_at) INCLUDE (is_live);
198
+ `);
199
+ await client.query(`
200
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_entity_status
201
+ ON ${fullTableName} (entity, status);
202
+ `);
203
+ await client.query(`
204
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_expired_at
205
+ ON ${fullTableName} (expired_at);
206
+ `);
207
+ // Create function to update is_live flag in the schema
208
+ await client.query(`
209
+ CREATE OR REPLACE FUNCTION ${schemaName}.update_is_live()
210
+ RETURNS TRIGGER AS $$
211
+ BEGIN
212
+ NEW.is_live := NEW.expired_at IS NULL OR NEW.expired_at > NOW();
213
+ RETURN NEW;
214
+ END;
215
+ $$ LANGUAGE plpgsql;
216
+ `);
217
+ // Create trigger for is_live updates
218
+ await client.query(`
219
+ CREATE TRIGGER trg_update_is_live
220
+ BEFORE INSERT OR UPDATE ON ${fullTableName}
221
+ FOR EACH ROW EXECUTE PROCEDURE ${schemaName}.update_is_live();
222
+ `);
223
+ // Create function to enforce uniqueness of live jobs
224
+ await client.query(`
225
+ CREATE OR REPLACE FUNCTION ${schemaName}.enforce_live_job_uniqueness()
226
+ RETURNS TRIGGER AS $$
227
+ BEGIN
228
+ IF (NEW.expired_at IS NULL OR NEW.expired_at > NOW()) THEN
229
+ PERFORM pg_advisory_xact_lock(hashtextextended(NEW.key, 0));
230
+ IF EXISTS (
231
+ SELECT 1 FROM ${fullTableName}
232
+ WHERE key = NEW.key
233
+ AND (expired_at IS NULL OR expired_at > NOW())
234
+ AND id <> NEW.id
235
+ ) THEN
236
+ RAISE EXCEPTION 'A live job with key % already exists.', NEW.key;
237
+ END IF;
238
+ END IF;
239
+ RETURN NEW;
240
+ END;
241
+ $$ LANGUAGE plpgsql;
242
+ `);
243
+ // Create trigger for uniqueness enforcement
244
+ await client.query(`
245
+ CREATE TRIGGER trg_enforce_live_job_uniqueness
246
+ BEFORE INSERT OR UPDATE ON ${fullTableName}
247
+ FOR EACH ROW EXECUTE PROCEDURE ${schemaName}.enforce_live_job_uniqueness();
248
+ `);
249
+ // Create the attributes table with partitioning
250
+ const attributesTableName = `${fullTableName}_attributes`;
251
+ await client.query(`
252
+ CREATE TABLE IF NOT EXISTS ${attributesTableName} (
253
+ job_id UUID NOT NULL,
254
+ field TEXT NOT NULL,
255
+ value TEXT,
256
+ type ${schemaName}.type_enum NOT NULL,
257
+ PRIMARY KEY (job_id, field),
258
+ FOREIGN KEY (job_id) REFERENCES ${fullTableName} (id) ON DELETE CASCADE
259
+ ) PARTITION BY HASH (job_id);
260
+ `);
261
+ // Create partitions for attributes table
262
+ await client.query(`
263
+ DO $$
264
+ BEGIN
265
+ FOR i IN 0..7 LOOP
266
+ EXECUTE format(
267
+ 'CREATE TABLE IF NOT EXISTS ${attributesTableName}_part_%s PARTITION OF ${attributesTableName}
268
+ FOR VALUES WITH (modulus 8, remainder %s)',
269
+ i, i
270
+ );
271
+ END LOOP;
272
+ END$$;
273
+ `);
274
+ // Create indexes for attributes table
275
+ await client.query(`
276
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_attributes_type_field
277
+ ON ${attributesTableName} (type, field);
278
+ `);
279
+ await client.query(`
280
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_attributes_field
281
+ ON ${attributesTableName} (field);
282
+ `);
283
+ break;
284
+ case 'list':
285
+ await client.query(`
286
+ CREATE TABLE IF NOT EXISTS ${fullTableName} (
287
+ key TEXT NOT NULL,
288
+ index BIGINT NOT NULL,
289
+ value TEXT,
290
+ expiry TIMESTAMP WITH TIME ZONE,
291
+ PRIMARY KEY (key, index)
292
+ );
293
+ `);
294
+ await client.query(`
295
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_key_expiry
296
+ ON ${fullTableName} (key, expiry);
297
+ `);
298
+ break;
299
+ case 'sorted_set':
300
+ await client.query(`
301
+ CREATE TABLE IF NOT EXISTS ${fullTableName} (
302
+ key TEXT NOT NULL,
303
+ member TEXT NOT NULL,
304
+ score DOUBLE PRECISION NOT NULL,
305
+ expiry TIMESTAMP WITH TIME ZONE,
306
+ PRIMARY KEY (key, member)
307
+ );
308
+ `);
309
+ await client.query(`
310
+ CREATE INDEX IF NOT EXISTS idx_${tableDef.name}_key_score_member
311
+ ON ${fullTableName} (key, score, member);
312
+ `);
313
+ break;
314
+ default:
315
+ context.logger.warn(`Unknown table type for ${tableDef.name}`);
316
+ break;
317
+ }
318
+ }
319
+ // Commit transaction
320
+ await client.query('COMMIT');
321
+ }
322
+ catch (error) {
323
+ context.logger.error('postgres-create-tables-error', { error });
324
+ await client.query('ROLLBACK');
325
+ throw error;
326
+ }
327
+ },
328
+ getTableNames(appName) {
329
+ const tableNames = [];
330
+ // Applications table (only hotmesh prefix)
331
+ tableNames.push('hotmesh_applications', 'hotmesh_connections');
332
+ // Other tables with appName
333
+ const tablesWithAppName = [
334
+ 'throttles',
335
+ 'roles',
336
+ 'task_priorities',
337
+ 'task_schedules',
338
+ 'task_lists',
339
+ 'events',
340
+ 'jobs',
341
+ 'stats_counted',
342
+ 'stats_indexed',
343
+ 'stats_ordered',
344
+ 'versions',
345
+ 'signal_patterns',
346
+ 'signal_registry',
347
+ 'symbols',
348
+ ];
349
+ tablesWithAppName.forEach((table) => {
350
+ tableNames.push(`${context.storeClient.safeName(appName)}.${table}`);
351
+ });
352
+ return tableNames;
353
+ },
354
+ getTableDefinitions(appName) {
355
+ const schemaName = context.storeClient.safeName(appName);
356
+ const tableDefinitions = [
357
+ {
358
+ schema: 'public',
359
+ name: 'hotmesh_applications',
360
+ type: 'hash',
361
+ },
362
+ {
363
+ schema: 'public',
364
+ name: 'hotmesh_connections',
365
+ type: 'hash',
366
+ },
367
+ {
368
+ schema: schemaName,
369
+ name: 'throttles',
370
+ type: 'hash',
371
+ },
372
+ {
373
+ schema: schemaName,
374
+ name: 'roles',
375
+ type: 'string',
376
+ },
377
+ {
378
+ schema: schemaName,
379
+ name: 'task_schedules',
380
+ type: 'sorted_set',
381
+ },
382
+ {
383
+ schema: schemaName,
384
+ name: 'task_priorities',
385
+ type: 'sorted_set',
386
+ },
387
+ {
388
+ schema: schemaName,
389
+ name: 'task_lists',
390
+ type: 'list',
391
+ },
392
+ {
393
+ schema: schemaName,
394
+ name: 'events',
395
+ type: 'hash',
396
+ },
397
+ {
398
+ schema: schemaName,
399
+ name: 'jobs',
400
+ type: 'jobhash', // Adds partitioning, indexes, and enum type
401
+ },
402
+ {
403
+ schema: schemaName,
404
+ name: 'stats_counted',
405
+ type: 'hash',
406
+ },
407
+ {
408
+ schema: schemaName,
409
+ name: 'stats_ordered',
410
+ type: 'sorted_set',
411
+ },
412
+ {
413
+ schema: schemaName,
414
+ name: 'stats_indexed',
415
+ type: 'list',
416
+ },
417
+ {
418
+ schema: schemaName,
419
+ name: 'versions',
420
+ type: 'hash',
421
+ },
422
+ {
423
+ schema: schemaName,
424
+ name: 'signal_patterns',
425
+ type: 'hash',
426
+ },
427
+ {
428
+ schema: schemaName,
429
+ name: 'symbols',
430
+ type: 'hash',
431
+ },
432
+ {
433
+ schema: schemaName,
434
+ name: 'signal_registry',
435
+ type: 'string',
436
+ },
437
+ ];
438
+ return tableDefinitions;
439
+ },
440
+ });
441
+ exports.KVTables = KVTables;
@@ -0,0 +1,36 @@
1
+ import { HSetOptions, KVSQLProviderTransaction, SetOptions, ZAddOptions } from '../../../../types/provider';
2
+ import type { KVSQL } from './kvsql';
3
+ export declare class KVTransaction implements KVSQLProviderTransaction {
4
+ private kvsql;
5
+ [key: string]: any;
6
+ private commands;
7
+ constructor(kvsql: KVSQL);
8
+ addCommand(sql: string, params: any[], returnType: string, transform?: (rows: any[]) => any): this;
9
+ set(key: string, value: string, options?: SetOptions): this;
10
+ setnx(key: string, value: string): this;
11
+ setnxex(key: string, value: string, expireSeconds: number): this;
12
+ get(key: string): this;
13
+ del(key: string): this;
14
+ expire(key: string, seconds: number): this;
15
+ hset(key: string, fields: Record<string, string>, options?: HSetOptions): this;
16
+ hget(key: string, field: string): this;
17
+ hdel(key: string, fields: string[]): this;
18
+ hmget(key: string, fields: string[]): this;
19
+ hgetall(key: string): this;
20
+ hincrbyfloat(key: string, field: string, increment: number): this;
21
+ hscan(key: string, cursor: string, count?: number): this;
22
+ lrange(key: string, start: number, end: number): this;
23
+ rpush(key: string, value: string | string[]): this;
24
+ lpush(key: string, value: string | string[]): this;
25
+ lpop(key: string): this;
26
+ lmove(source: string, destination: string, srcPosition: 'LEFT' | 'RIGHT', destPosition: 'LEFT' | 'RIGHT'): this;
27
+ zadd(key: string, score: number, member: string, options?: ZAddOptions): this;
28
+ zrange(key: string, start: number, stop: number): this;
29
+ zrangebyscore(key: string, min: number, max: number): this;
30
+ zrangebyscore_withscores(key: string, min: number, max: number): this;
31
+ zrem(key: string, member: string): this;
32
+ zrank(key: string, member: string): this;
33
+ scan(cursor: number, count?: number): this;
34
+ rename(oldKey: string, newKey: string): this;
35
+ exec(): Promise<any[]>;
36
+ }