bunqueue 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +640 -0
  3. package/dist/application/dlqManager.d.ts +19 -0
  4. package/dist/application/dlqManager.d.ts.map +1 -0
  5. package/dist/application/dlqManager.js +44 -0
  6. package/dist/application/dlqManager.js.map +1 -0
  7. package/dist/application/eventsManager.d.ts +28 -0
  8. package/dist/application/eventsManager.d.ts.map +1 -0
  9. package/dist/application/eventsManager.js +59 -0
  10. package/dist/application/eventsManager.js.map +1 -0
  11. package/dist/application/jobLogsManager.d.ts +20 -0
  12. package/dist/application/jobLogsManager.d.ts.map +1 -0
  13. package/dist/application/jobLogsManager.js +28 -0
  14. package/dist/application/jobLogsManager.js.map +1 -0
  15. package/dist/application/metricsExporter.d.ts +24 -0
  16. package/dist/application/metricsExporter.d.ts.map +1 -0
  17. package/dist/application/metricsExporter.js +80 -0
  18. package/dist/application/metricsExporter.js.map +1 -0
  19. package/dist/application/operations/ack.d.ts +48 -0
  20. package/dist/application/operations/ack.d.ts.map +1 -0
  21. package/dist/application/operations/ack.js +109 -0
  22. package/dist/application/operations/ack.js.map +1 -0
  23. package/dist/application/operations/index.d.ts +10 -0
  24. package/dist/application/operations/index.d.ts.map +1 -0
  25. package/dist/application/operations/index.js +10 -0
  26. package/dist/application/operations/index.js.map +1 -0
  27. package/dist/application/operations/jobManagement.d.ts +32 -0
  28. package/dist/application/operations/jobManagement.d.ts.map +1 -0
  29. package/dist/application/operations/jobManagement.js +122 -0
  30. package/dist/application/operations/jobManagement.js.map +1 -0
  31. package/dist/application/operations/pull.d.ts +36 -0
  32. package/dist/application/operations/pull.d.ts.map +1 -0
  33. package/dist/application/operations/pull.js +109 -0
  34. package/dist/application/operations/pull.js.map +1 -0
  35. package/dist/application/operations/push.d.ts +36 -0
  36. package/dist/application/operations/push.d.ts.map +1 -0
  37. package/dist/application/operations/push.js +94 -0
  38. package/dist/application/operations/push.js.map +1 -0
  39. package/dist/application/operations/queryOperations.d.ts +33 -0
  40. package/dist/application/operations/queryOperations.d.ts.map +1 -0
  41. package/dist/application/operations/queryOperations.js +57 -0
  42. package/dist/application/operations/queryOperations.js.map +1 -0
  43. package/dist/application/operations/queueControl.d.ts +32 -0
  44. package/dist/application/operations/queueControl.d.ts.map +1 -0
  45. package/dist/application/operations/queueControl.js +72 -0
  46. package/dist/application/operations/queueControl.js.map +1 -0
  47. package/dist/application/queueManager.d.ts +113 -0
  48. package/dist/application/queueManager.d.ts.map +1 -0
  49. package/dist/application/queueManager.js +406 -0
  50. package/dist/application/queueManager.js.map +1 -0
  51. package/dist/application/webhookManager.d.ts +35 -0
  52. package/dist/application/webhookManager.d.ts.map +1 -0
  53. package/dist/application/webhookManager.js +109 -0
  54. package/dist/application/webhookManager.js.map +1 -0
  55. package/dist/application/workerManager.d.ts +48 -0
  56. package/dist/application/workerManager.d.ts.map +1 -0
  57. package/dist/application/workerManager.js +121 -0
  58. package/dist/application/workerManager.js.map +1 -0
  59. package/dist/domain/queue/index.d.ts +6 -0
  60. package/dist/domain/queue/index.d.ts.map +1 -0
  61. package/dist/domain/queue/index.js +6 -0
  62. package/dist/domain/queue/index.js.map +1 -0
  63. package/dist/domain/queue/priorityQueue.d.ts +45 -0
  64. package/dist/domain/queue/priorityQueue.d.ts.map +1 -0
  65. package/dist/domain/queue/priorityQueue.js +203 -0
  66. package/dist/domain/queue/priorityQueue.js.map +1 -0
  67. package/dist/domain/queue/shard.d.ts +98 -0
  68. package/dist/domain/queue/shard.d.ts.map +1 -0
  69. package/dist/domain/queue/shard.js +245 -0
  70. package/dist/domain/queue/shard.js.map +1 -0
  71. package/dist/domain/types/command.d.ts +270 -0
  72. package/dist/domain/types/command.d.ts.map +1 -0
  73. package/dist/domain/types/command.js +6 -0
  74. package/dist/domain/types/command.js.map +1 -0
  75. package/dist/domain/types/cron.d.ts +32 -0
  76. package/dist/domain/types/cron.d.ts.map +1 -0
  77. package/dist/domain/types/cron.js +31 -0
  78. package/dist/domain/types/cron.js.map +1 -0
  79. package/dist/domain/types/index.d.ts +9 -0
  80. package/dist/domain/types/index.d.ts.map +1 -0
  81. package/dist/domain/types/index.js +9 -0
  82. package/dist/domain/types/index.js.map +1 -0
  83. package/dist/domain/types/job.d.ts +94 -0
  84. package/dist/domain/types/job.d.ts.map +1 -0
  85. package/dist/domain/types/job.js +81 -0
  86. package/dist/domain/types/job.js.map +1 -0
  87. package/dist/domain/types/queue.d.ts +86 -0
  88. package/dist/domain/types/queue.d.ts.map +1 -0
  89. package/dist/domain/types/queue.js +84 -0
  90. package/dist/domain/types/queue.js.map +1 -0
  91. package/dist/domain/types/response.d.ts +158 -0
  92. package/dist/domain/types/response.d.ts.map +1 -0
  93. package/dist/domain/types/response.js +86 -0
  94. package/dist/domain/types/response.js.map +1 -0
  95. package/dist/domain/types/webhook.d.ts +33 -0
  96. package/dist/domain/types/webhook.d.ts.map +1 -0
  97. package/dist/domain/types/webhook.js +20 -0
  98. package/dist/domain/types/webhook.js.map +1 -0
  99. package/dist/domain/types/worker.d.ts +27 -0
  100. package/dist/domain/types/worker.d.ts.map +1 -0
  101. package/dist/domain/types/worker.js +27 -0
  102. package/dist/domain/types/worker.js.map +1 -0
  103. package/dist/infrastructure/persistence/index.d.ts +6 -0
  104. package/dist/infrastructure/persistence/index.d.ts.map +1 -0
  105. package/dist/infrastructure/persistence/index.js +6 -0
  106. package/dist/infrastructure/persistence/index.js.map +1 -0
  107. package/dist/infrastructure/persistence/schema.d.ts +14 -0
  108. package/dist/infrastructure/persistence/schema.d.ts.map +1 -0
  109. package/dist/infrastructure/persistence/schema.js +123 -0
  110. package/dist/infrastructure/persistence/schema.js.map +1 -0
  111. package/dist/infrastructure/persistence/sqlite.d.ts +42 -0
  112. package/dist/infrastructure/persistence/sqlite.d.ts.map +1 -0
  113. package/dist/infrastructure/persistence/sqlite.js +164 -0
  114. package/dist/infrastructure/persistence/sqlite.js.map +1 -0
  115. package/dist/infrastructure/persistence/statements.d.ts +55 -0
  116. package/dist/infrastructure/persistence/statements.d.ts.map +1 -0
  117. package/dist/infrastructure/persistence/statements.js +42 -0
  118. package/dist/infrastructure/persistence/statements.js.map +1 -0
  119. package/dist/infrastructure/scheduler/cronParser.d.ts +44 -0
  120. package/dist/infrastructure/scheduler/cronParser.d.ts.map +1 -0
  121. package/dist/infrastructure/scheduler/cronParser.js +90 -0
  122. package/dist/infrastructure/scheduler/cronParser.js.map +1 -0
  123. package/dist/infrastructure/scheduler/cronScheduler.d.ts +68 -0
  124. package/dist/infrastructure/scheduler/cronScheduler.d.ts.map +1 -0
  125. package/dist/infrastructure/scheduler/cronScheduler.js +172 -0
  126. package/dist/infrastructure/scheduler/cronScheduler.js.map +1 -0
  127. package/dist/infrastructure/scheduler/index.d.ts +6 -0
  128. package/dist/infrastructure/scheduler/index.d.ts.map +1 -0
  129. package/dist/infrastructure/scheduler/index.js +6 -0
  130. package/dist/infrastructure/scheduler/index.js.map +1 -0
  131. package/dist/infrastructure/server/handler.d.ts +13 -0
  132. package/dist/infrastructure/server/handler.d.ts.map +1 -0
  133. package/dist/infrastructure/server/handler.js +167 -0
  134. package/dist/infrastructure/server/handler.js.map +1 -0
  135. package/dist/infrastructure/server/handlers/advanced.d.ts +68 -0
  136. package/dist/infrastructure/server/handlers/advanced.d.ts.map +1 -0
  137. package/dist/infrastructure/server/handlers/advanced.js +99 -0
  138. package/dist/infrastructure/server/handlers/advanced.js.map +1 -0
  139. package/dist/infrastructure/server/handlers/core.d.ts +36 -0
  140. package/dist/infrastructure/server/handlers/core.d.ts.map +1 -0
  141. package/dist/infrastructure/server/handlers/core.js +82 -0
  142. package/dist/infrastructure/server/handlers/core.js.map +1 -0
  143. package/dist/infrastructure/server/handlers/cron.d.ts +20 -0
  144. package/dist/infrastructure/server/handlers/cron.d.ts.map +1 -0
  145. package/dist/infrastructure/server/handlers/cron.js +56 -0
  146. package/dist/infrastructure/server/handlers/cron.js.map +1 -0
  147. package/dist/infrastructure/server/handlers/dlq.d.ts +20 -0
  148. package/dist/infrastructure/server/handlers/dlq.d.ts.map +1 -0
  149. package/dist/infrastructure/server/handlers/dlq.js +31 -0
  150. package/dist/infrastructure/server/handlers/dlq.js.map +1 -0
  151. package/dist/infrastructure/server/handlers/index.d.ts +7 -0
  152. package/dist/infrastructure/server/handlers/index.d.ts.map +1 -0
  153. package/dist/infrastructure/server/handlers/index.js +7 -0
  154. package/dist/infrastructure/server/handlers/index.js.map +1 -0
  155. package/dist/infrastructure/server/handlers/management.d.ts +36 -0
  156. package/dist/infrastructure/server/handlers/management.d.ts.map +1 -0
  157. package/dist/infrastructure/server/handlers/management.js +75 -0
  158. package/dist/infrastructure/server/handlers/management.js.map +1 -0
  159. package/dist/infrastructure/server/handlers/monitoring.d.ts +18 -0
  160. package/dist/infrastructure/server/handlers/monitoring.d.ts.map +1 -0
  161. package/dist/infrastructure/server/handlers/monitoring.js +102 -0
  162. package/dist/infrastructure/server/handlers/monitoring.js.map +1 -0
  163. package/dist/infrastructure/server/handlers/query.d.ts +32 -0
  164. package/dist/infrastructure/server/handlers/query.d.ts.map +1 -0
  165. package/dist/infrastructure/server/handlers/query.js +61 -0
  166. package/dist/infrastructure/server/handlers/query.js.map +1 -0
  167. package/dist/infrastructure/server/http.d.ts +43 -0
  168. package/dist/infrastructure/server/http.d.ts.map +1 -0
  169. package/dist/infrastructure/server/http.js +344 -0
  170. package/dist/infrastructure/server/http.js.map +1 -0
  171. package/dist/infrastructure/server/index.d.ts +8 -0
  172. package/dist/infrastructure/server/index.d.ts.map +1 -0
  173. package/dist/infrastructure/server/index.js +8 -0
  174. package/dist/infrastructure/server/index.js.map +1 -0
  175. package/dist/infrastructure/server/protocol.d.ts +44 -0
  176. package/dist/infrastructure/server/protocol.d.ts.map +1 -0
  177. package/dist/infrastructure/server/protocol.js +129 -0
  178. package/dist/infrastructure/server/protocol.js.map +1 -0
  179. package/dist/infrastructure/server/rateLimiter.d.ts +31 -0
  180. package/dist/infrastructure/server/rateLimiter.d.ts.map +1 -0
  181. package/dist/infrastructure/server/rateLimiter.js +79 -0
  182. package/dist/infrastructure/server/rateLimiter.js.map +1 -0
  183. package/dist/infrastructure/server/tcp.d.ts +36 -0
  184. package/dist/infrastructure/server/tcp.d.ts.map +1 -0
  185. package/dist/infrastructure/server/tcp.js +101 -0
  186. package/dist/infrastructure/server/tcp.js.map +1 -0
  187. package/dist/infrastructure/server/types.d.ts +11 -0
  188. package/dist/infrastructure/server/types.d.ts.map +1 -0
  189. package/dist/infrastructure/server/types.js +5 -0
  190. package/dist/infrastructure/server/types.js.map +1 -0
  191. package/dist/main.d.ts +6 -0
  192. package/dist/main.d.ts.map +1 -0
  193. package/dist/main.js +111 -0
  194. package/dist/main.js.map +1 -0
  195. package/dist/shared/hash.d.ts +30 -0
  196. package/dist/shared/hash.d.ts.map +1 -0
  197. package/dist/shared/hash.js +69 -0
  198. package/dist/shared/hash.js.map +1 -0
  199. package/dist/shared/index.d.ts +6 -0
  200. package/dist/shared/index.d.ts.map +1 -0
  201. package/dist/shared/index.js +6 -0
  202. package/dist/shared/index.js.map +1 -0
  203. package/dist/shared/lock.d.ts +70 -0
  204. package/dist/shared/lock.d.ts.map +1 -0
  205. package/dist/shared/lock.js +207 -0
  206. package/dist/shared/lock.js.map +1 -0
  207. package/dist/shared/logger.d.ts +38 -0
  208. package/dist/shared/logger.d.ts.map +1 -0
  209. package/dist/shared/logger.js +74 -0
  210. package/dist/shared/logger.js.map +1 -0
  211. package/dist/shared/serialization.d.ts +23 -0
  212. package/dist/shared/serialization.d.ts.map +1 -0
  213. package/dist/shared/serialization.js +63 -0
  214. package/dist/shared/serialization.js.map +1 -0
  215. package/package.json +82 -0
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Protocol Rate Limiter
3
+ * Prevents abuse by limiting requests per client
4
+ */
5
+ const DEFAULT_CONFIG = {
6
+ windowMs: 60_000,
7
+ maxRequests: 1000,
8
+ cleanupIntervalMs: 60_000,
9
+ };
10
+ /** Rate limiter for protocol-level request limiting */
11
+ export class ProtocolRateLimiter {
12
+ requests = new Map();
13
+ config;
14
+ cleanupInterval = null;
15
+ constructor(config = {}) {
16
+ this.config = { ...DEFAULT_CONFIG, ...config };
17
+ this.startCleanup();
18
+ }
19
+ /** Check if a request from clientId is allowed */
20
+ isAllowed(clientId) {
21
+ const now = Date.now();
22
+ const timestamps = this.requests.get(clientId) ?? [];
23
+ // Remove timestamps outside the window
24
+ const valid = timestamps.filter((t) => now - t < this.config.windowMs);
25
+ if (valid.length >= this.config.maxRequests) {
26
+ return false;
27
+ }
28
+ valid.push(now);
29
+ this.requests.set(clientId, valid);
30
+ return true;
31
+ }
32
+ /** Get remaining requests for a client */
33
+ getRemaining(clientId) {
34
+ const now = Date.now();
35
+ const timestamps = this.requests.get(clientId) ?? [];
36
+ const valid = timestamps.filter((t) => now - t < this.config.windowMs);
37
+ return Math.max(0, this.config.maxRequests - valid.length);
38
+ }
39
+ /** Remove a client from tracking */
40
+ removeClient(clientId) {
41
+ this.requests.delete(clientId);
42
+ }
43
+ /** Start cleanup interval */
44
+ startCleanup() {
45
+ if (this.config.cleanupIntervalMs) {
46
+ this.cleanupInterval = setInterval(() => {
47
+ this.cleanup();
48
+ }, this.config.cleanupIntervalMs);
49
+ }
50
+ }
51
+ /** Clean up old entries */
52
+ cleanup() {
53
+ const now = Date.now();
54
+ for (const [clientId, timestamps] of this.requests) {
55
+ const valid = timestamps.filter((t) => now - t < this.config.windowMs);
56
+ if (valid.length === 0) {
57
+ this.requests.delete(clientId);
58
+ }
59
+ else {
60
+ this.requests.set(clientId, valid);
61
+ }
62
+ }
63
+ }
64
+ /** Stop the rate limiter */
65
+ stop() {
66
+ if (this.cleanupInterval) {
67
+ clearInterval(this.cleanupInterval);
68
+ this.cleanupInterval = null;
69
+ }
70
+ }
71
+ }
72
+ /** Global rate limiter instance */
73
+ let globalRateLimiter = null;
74
+ /** Get or create global rate limiter */
75
+ export function getRateLimiter(config) {
76
+ globalRateLimiter ??= new ProtocolRateLimiter(config);
77
+ return globalRateLimiter;
78
+ }
79
+ //# sourceMappingURL=rateLimiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../../../src/infrastructure/server/rateLimiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * TCP Server
3
+ * Handles TCP connections with JSON line protocol
4
+ */
5
+ import type { Socket } from 'bun';
6
+ import type { QueueManager } from '../../application/queueManager';
7
+ import { type HandlerContext } from './handler';
8
+ import { LineBuffer, type ConnectionState } from './protocol';
9
+ /** TCP Server configuration */
10
+ export interface TcpServerConfig {
11
+ port: number;
12
+ hostname?: string;
13
+ authTokens?: string[];
14
+ }
15
+ /** Per-connection data */
16
+ interface ConnectionData {
17
+ state: ConnectionState;
18
+ buffer: LineBuffer;
19
+ ctx: HandlerContext;
20
+ }
21
+ /**
22
+ * Create and start TCP server
23
+ */
24
+ export declare function createTcpServer(queueManager: QueueManager, config: TcpServerConfig): {
25
+ server: Bun.TCPSocketListener<ConnectionData>;
26
+ connections: Map<string, Socket<ConnectionData>>;
27
+ /** Get connection count */
28
+ getConnectionCount(): number;
29
+ /** Broadcast to all connections */
30
+ broadcast(message: string): void;
31
+ /** Stop the server */
32
+ stop(): void;
33
+ };
34
+ export type TcpServer = ReturnType<typeof createTcpServer>;
35
+ export {};
36
+ //# sourceMappingURL=tcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tcp.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/server/tcp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EACL,UAAU,EAKV,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAKpB,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,0BAA0B;AAC1B,UAAU,cAAc;IACtB,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,cAAc,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe;;;IAgF/E,2BAA2B;0BACL,MAAM;IAI5B,mCAAmC;uBAChB,MAAM,GAAG,IAAI;IAMhC,sBAAsB;YACd,IAAI;EASf;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * TCP Server
3
+ * Handles TCP connections with JSON line protocol
4
+ */
5
+ import { handleCommand } from './handler';
6
+ import { LineBuffer, parseCommand, serializeResponse, errorResponse, createConnectionState, } from './protocol';
7
+ import { uuid } from '../../shared/hash';
8
+ import { tcpLog } from '../../shared/logger';
9
+ import { getRateLimiter } from './rateLimiter';
10
+ /**
11
+ * Create and start TCP server
12
+ */
13
+ export function createTcpServer(queueManager, config) {
14
+ const authTokens = new Set(config.authTokens ?? []);
15
+ const connections = new Map();
16
+ const server = Bun.listen({
17
+ hostname: config.hostname ?? '0.0.0.0',
18
+ port: config.port,
19
+ socket: {
20
+ open(socket) {
21
+ const clientId = uuid();
22
+ const state = createConnectionState(clientId);
23
+ const ctx = {
24
+ queueManager,
25
+ authTokens,
26
+ authenticated: authTokens.size === 0, // Auto-auth if no tokens
27
+ };
28
+ socket.data = {
29
+ state,
30
+ buffer: new LineBuffer(),
31
+ ctx,
32
+ };
33
+ connections.set(clientId, socket);
34
+ tcpLog.info('Client connected', { clientId });
35
+ },
36
+ async data(socket, data) {
37
+ const { buffer, ctx, state } = socket.data;
38
+ const rateLimiter = getRateLimiter();
39
+ // Check rate limit
40
+ if (!rateLimiter.isAllowed(state.clientId)) {
41
+ socket.write(errorResponse('Rate limit exceeded') + '\n');
42
+ return;
43
+ }
44
+ const text = new TextDecoder().decode(data);
45
+ const lines = buffer.addData(text);
46
+ for (const line of lines) {
47
+ const cmd = parseCommand(line);
48
+ if (!cmd) {
49
+ socket.write(errorResponse('Invalid command') + '\n');
50
+ continue;
51
+ }
52
+ try {
53
+ const response = await handleCommand(cmd, ctx);
54
+ socket.write(serializeResponse(response) + '\n');
55
+ }
56
+ catch (err) {
57
+ const message = err instanceof Error ? err.message : 'Unknown error';
58
+ socket.write(errorResponse(message, cmd.reqId) + '\n');
59
+ }
60
+ }
61
+ },
62
+ close(socket) {
63
+ const clientId = socket.data.state.clientId;
64
+ connections.delete(clientId);
65
+ getRateLimiter().removeClient(clientId);
66
+ tcpLog.info('Client disconnected', { clientId });
67
+ },
68
+ error(_socket, error) {
69
+ tcpLog.error('Connection error', { error: error.message });
70
+ },
71
+ drain(_socket) {
72
+ // Called when socket is ready for more writes after backpressure
73
+ },
74
+ },
75
+ });
76
+ tcpLog.info('Server listening', { host: config.hostname ?? '0.0.0.0', port: config.port });
77
+ return {
78
+ server,
79
+ connections,
80
+ /** Get connection count */
81
+ getConnectionCount() {
82
+ return connections.size;
83
+ },
84
+ /** Broadcast to all connections */
85
+ broadcast(message) {
86
+ for (const socket of connections.values()) {
87
+ socket.write(message + '\n');
88
+ }
89
+ },
90
+ /** Stop the server */
91
+ stop() {
92
+ server.stop();
93
+ for (const socket of connections.values()) {
94
+ socket.end();
95
+ }
96
+ connections.clear();
97
+ tcpLog.info('Server stopped');
98
+ },
99
+ };
100
+ }
101
+ //# sourceMappingURL=tcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tcp.js","sourceRoot":"","sources":["../../../src/infrastructure/server/tcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Server types
3
+ */
4
+ import type { QueueManager } from '../../application/queueManager';
5
+ /** Handler context passed to all command handlers */
6
+ export interface HandlerContext {
7
+ queueManager: QueueManager;
8
+ authTokens: Set<string>;
9
+ authenticated: boolean;
10
+ }
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/server/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;CACxB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Server types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/infrastructure/server/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * bunQ - High-performance job queue server for Bun
3
+ * Main entry point
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
package/dist/main.js ADDED
@@ -0,0 +1,111 @@
1
+ /**
2
+ * bunQ - High-performance job queue server for Bun
3
+ * Main entry point
4
+ */
5
+ import { QueueManager } from './application/queueManager';
6
+ import { createTcpServer } from './infrastructure/server/tcp';
7
+ import { createHttpServer } from './infrastructure/server/http';
8
+ import { Logger, serverLog, statsLog } from './shared/logger';
9
+ /** Load configuration from environment variables */
10
+ function loadConfig() {
11
+ return {
12
+ tcpPort: parseInt(process.env.TCP_PORT ?? '6789'),
13
+ httpPort: parseInt(process.env.HTTP_PORT ?? '6790'),
14
+ hostname: process.env.HOST ?? '0.0.0.0',
15
+ authTokens: process.env.AUTH_TOKENS?.split(',').filter(Boolean) ?? [],
16
+ dataPath: process.env.DATA_PATH ?? process.env.SQLITE_PATH,
17
+ corsOrigins: process.env.CORS_ALLOW_ORIGIN?.split(',').filter(Boolean) ?? ['*'],
18
+ requireAuthForMetrics: process.env.METRICS_AUTH === 'true',
19
+ };
20
+ }
21
+ /** Print startup banner */
22
+ function printBanner(config) {
23
+ console.log(`
24
+ ╔═══════════════════════════════════════════════════════════╗
25
+ ║ ║
26
+ ║ 🐰 bunQ ║
27
+ ║ High-performance job queue server for Bun ║
28
+ ║ ║
29
+ ╠═══════════════════════════════════════════════════════════╣
30
+ ║ ║
31
+ ║ TCP Port: ${String(config.tcpPort).padEnd(44)}║
32
+ ║ HTTP Port: ${String(config.httpPort).padEnd(44)}║
33
+ ║ Host: ${config.hostname.padEnd(44)}║
34
+ ║ Auth: ${(config.authTokens.length > 0 ? 'Enabled' : 'Disabled').padEnd(44)}║
35
+ ║ Storage: ${(config.dataPath ?? 'In-memory').padEnd(44)}║
36
+ ║ ║
37
+ ╚═══════════════════════════════════════════════════════════╝
38
+ `);
39
+ }
40
+ /** Main function */
41
+ function main() {
42
+ const config = loadConfig();
43
+ printBanner(config);
44
+ // Create queue manager
45
+ const queueManager = new QueueManager({
46
+ dataPath: config.dataPath,
47
+ });
48
+ // Start TCP server
49
+ const tcpServer = createTcpServer(queueManager, {
50
+ port: config.tcpPort,
51
+ hostname: config.hostname,
52
+ authTokens: config.authTokens,
53
+ });
54
+ // Start HTTP server
55
+ const httpServer = createHttpServer(queueManager, {
56
+ port: config.httpPort,
57
+ hostname: config.hostname,
58
+ authTokens: config.authTokens,
59
+ corsOrigins: config.corsOrigins,
60
+ requireAuthForMetrics: config.requireAuthForMetrics,
61
+ });
62
+ // Graceful shutdown
63
+ const shutdown = async (signal) => {
64
+ serverLog.info(`Received ${signal}, shutting down...`);
65
+ tcpServer.stop();
66
+ httpServer.stop();
67
+ const shutdownTimeout = 30_000;
68
+ const start = Date.now();
69
+ while (Date.now() - start < shutdownTimeout) {
70
+ const stats = queueManager.getStats();
71
+ if (stats.active === 0)
72
+ break;
73
+ serverLog.info(`Waiting for ${stats.active} active jobs...`);
74
+ await new Promise((r) => setTimeout(r, 1000));
75
+ }
76
+ queueManager.shutdown();
77
+ serverLog.info('Shutdown complete');
78
+ process.exit(0);
79
+ };
80
+ process.on('SIGINT', () => void shutdown('SIGINT'));
81
+ process.on('SIGTERM', () => void shutdown('SIGTERM'));
82
+ // Print stats periodically
83
+ setInterval(() => {
84
+ const stats = queueManager.getStats();
85
+ const workerStats = queueManager.workerManager.getStats();
86
+ statsLog.info('Queue statistics', {
87
+ waiting: stats.waiting,
88
+ active: stats.active,
89
+ delayed: stats.delayed,
90
+ completed: stats.completed,
91
+ dlq: stats.dlq,
92
+ tcp: tcpServer.getConnectionCount(),
93
+ ws: httpServer.getWsClientCount(),
94
+ sse: httpServer.getSseClientCount(),
95
+ workers: `${workerStats.active}/${workerStats.total}`,
96
+ });
97
+ }, 30_000);
98
+ }
99
+ // Enable JSON logging if requested
100
+ if (process.env.LOG_FORMAT === 'json') {
101
+ Logger.enableJsonMode();
102
+ }
103
+ // Run
104
+ try {
105
+ main();
106
+ }
107
+ catch (err) {
108
+ serverLog.error('Fatal error', { error: String(err) });
109
+ process.exit(1);
110
+ }
111
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Fast hash functions
3
+ * FNV-1a implementation for consistent hashing
4
+ */
5
+ /**
6
+ * FNV-1a hash function (32-bit)
7
+ * Fast, good distribution for strings
8
+ */
9
+ export declare function fnv1a(str: string): number;
10
+ /**
11
+ * Calculate shard index from string
12
+ * Uses 32 shards (& 0x1F mask)
13
+ */
14
+ export declare const SHARD_COUNT = 32;
15
+ export declare const SHARD_MASK = 31;
16
+ export declare function shardIndex(key: string): number;
17
+ /**
18
+ * Calculate processing shard index from job ID
19
+ */
20
+ export declare function processingShardIndex(jobId: bigint): number;
21
+ /**
22
+ * Generate a simple UUID v4
23
+ */
24
+ export declare function uuid(): string;
25
+ /**
26
+ * Constant-time string comparison
27
+ * Prevents timing attacks on token validation
28
+ */
29
+ export declare function constantTimeEqual(a: string, b: string): boolean;
30
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/shared/hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOzC;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,UAAU,KAAO,CAAC;AAE/B,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,IAAI,IAAI,MAAM,CAe7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO/D"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Fast hash functions
3
+ * FNV-1a implementation for consistent hashing
4
+ */
5
+ const FNV_PRIME = 0x01000193;
6
+ const FNV_OFFSET = 0x811c9dc5;
7
+ /**
8
+ * FNV-1a hash function (32-bit)
9
+ * Fast, good distribution for strings
10
+ */
11
+ export function fnv1a(str) {
12
+ let hash = FNV_OFFSET;
13
+ for (let i = 0; i < str.length; i++) {
14
+ hash ^= str.charCodeAt(i);
15
+ hash = Math.imul(hash, FNV_PRIME);
16
+ }
17
+ return hash >>> 0; // Convert to unsigned 32-bit
18
+ }
19
+ /**
20
+ * Calculate shard index from string
21
+ * Uses 32 shards (& 0x1F mask)
22
+ */
23
+ export const SHARD_COUNT = 32;
24
+ export const SHARD_MASK = 0x1f;
25
+ export function shardIndex(key) {
26
+ return fnv1a(key) & SHARD_MASK;
27
+ }
28
+ /**
29
+ * Calculate processing shard index from job ID
30
+ */
31
+ export function processingShardIndex(jobId) {
32
+ return Number(jobId & BigInt(SHARD_MASK));
33
+ }
34
+ /**
35
+ * Generate a simple UUID v4
36
+ */
37
+ export function uuid() {
38
+ const hex = '0123456789abcdef';
39
+ let result = '';
40
+ for (let i = 0; i < 36; i++) {
41
+ if (i === 8 || i === 13 || i === 18 || i === 23) {
42
+ result += '-';
43
+ }
44
+ else if (i === 14) {
45
+ result += '4';
46
+ }
47
+ else if (i === 19) {
48
+ result += hex[(Math.random() * 4) | 8];
49
+ }
50
+ else {
51
+ result += hex[(Math.random() * 16) | 0];
52
+ }
53
+ }
54
+ return result;
55
+ }
56
+ /**
57
+ * Constant-time string comparison
58
+ * Prevents timing attacks on token validation
59
+ */
60
+ export function constantTimeEqual(a, b) {
61
+ if (a.length !== b.length)
62
+ return false;
63
+ let result = 0;
64
+ for (let i = 0; i < a.length; i++) {
65
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
66
+ }
67
+ return result === 0;
68
+ }
69
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/shared/hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,SAAS,GAAG,UAAU,CAAC;AAC7B,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,6BAA6B;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC;AAE/B,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,IAAI;IAClB,MAAM,GAAG,GAAG,kBAAkB,CAAC;IAC/B,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,CAAC;QAChB,CAAC;aAAM,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,CAAC;QAChB,CAAC;aAAM,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAS,EAAE,CAAS;IACpD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,KAAK,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shared utilities barrel export
3
+ */
4
+ export * from './hash';
5
+ export * from './lock';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shared utilities barrel export
3
+ */
4
+ export * from './hash';
5
+ export * from './lock';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Async Lock implementation
3
+ * Provides read-write locks with timeout support
4
+ */
5
+ /** Lock acquisition result */
6
+ export interface LockGuard {
7
+ release(): void;
8
+ }
9
+ /** Lock timeout error */
10
+ export declare class LockTimeoutError extends Error {
11
+ constructor(message?: string);
12
+ }
13
+ /**
14
+ * Simple async mutex lock
15
+ * FIFO ordering for fairness
16
+ */
17
+ export declare class AsyncLock {
18
+ private locked;
19
+ private readonly queue;
20
+ /**
21
+ * Acquire the lock
22
+ * @param timeoutMs - Maximum time to wait (default: 5000ms)
23
+ */
24
+ acquire(timeoutMs?: number): Promise<LockGuard>;
25
+ /** Check if lock is held */
26
+ isLocked(): boolean;
27
+ /** Get queue length */
28
+ getQueueLength(): number;
29
+ }
30
+ /**
31
+ * Read-Write Lock
32
+ * Multiple readers OR single writer
33
+ * Writers have priority to prevent starvation
34
+ */
35
+ export declare class RWLock {
36
+ private readers;
37
+ private writer;
38
+ private writerWaiting;
39
+ private readonly readerQueue;
40
+ private readonly writerQueue;
41
+ /**
42
+ * Acquire read lock
43
+ * Multiple readers can hold simultaneously
44
+ */
45
+ acquireRead(timeoutMs?: number): Promise<LockGuard>;
46
+ /**
47
+ * Acquire write lock
48
+ * Exclusive access, no readers or other writers
49
+ */
50
+ acquireWrite(timeoutMs?: number): Promise<LockGuard>;
51
+ /** Get current state */
52
+ getState(): {
53
+ readers: number;
54
+ writer: boolean;
55
+ writerWaiting: number;
56
+ };
57
+ }
58
+ /**
59
+ * Execute with lock, ensuring release on error
60
+ */
61
+ export declare function withLock<T>(lock: AsyncLock, fn: () => T | Promise<T>, timeoutMs?: number): Promise<T>;
62
+ /**
63
+ * Execute with read lock
64
+ */
65
+ export declare function withReadLock<T>(lock: RWLock, fn: () => T | Promise<T>, timeoutMs?: number): Promise<T>;
66
+ /**
67
+ * Execute with write lock
68
+ */
69
+ export declare function withWriteLock<T>(lock: RWLock, fn: () => T | Promise<T>, timeoutMs?: number): Promise<T>;
70
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/shared/lock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8BAA8B;AAC9B,MAAM,WAAW,SAAS;IACxB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,yBAAyB;AACzB,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,GAAE,MAAqC;CAI3D;AAED;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAE/C;;;OAGG;IACG,OAAO,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAkC3D,4BAA4B;IAC5B,QAAQ,IAAI,OAAO;IAInB,uBAAuB;IACvB,cAAc,IAAI,MAAM;CAGzB;AAED;;;;GAIG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IAErD;;;OAGG;IACG,WAAW,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAqC/D;;;OAGG;IACG,YAAY,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAkDhE,wBAAwB;IACxB,QAAQ,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE;CAOxE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAOZ"}