@devbro/pashmak 0.1.19 → 0.1.21

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.
@@ -492,19 +492,7 @@ var FlexibleFactory = class {
492
492
  return ctor(...args);
493
493
  }
494
494
  };
495
- var MailerFactory = class _MailerFactory {
496
- static {
497
- __name(this, "MailerFactory");
498
- }
499
- static instance = new FlexibleFactory();
500
- static register(key, factory) {
501
- _MailerFactory.instance.register(key, factory);
502
- }
503
- static create(key, ...args) {
504
- return _MailerFactory.instance.create(key, ...args);
505
- }
506
- };
507
- MailerFactory.register("logger", (opt) => {
495
+ import_neko_mailer.MailerProviderFactory.register("logger", (opt) => {
508
496
  return new import_neko_mailer.FunctionProvider((mail) => {
509
497
  logger().info({
510
498
  msg: "Sending email",
@@ -512,32 +500,20 @@ MailerFactory.register("logger", (opt) => {
512
500
  });
513
501
  });
514
502
  });
515
- MailerFactory.register("ses", (opt) => {
503
+ import_neko_mailer.MailerProviderFactory.register("ses", (opt) => {
516
504
  return new import_neko_mailer.SESProvider(opt);
517
505
  });
518
- MailerFactory.register("smtp", (opt) => {
506
+ import_neko_mailer.MailerProviderFactory.register("smtp", (opt) => {
519
507
  return new import_neko_mailer.SMTPProvider(opt);
520
508
  });
521
- MailerFactory.register("memory", (opt) => {
509
+ import_neko_mailer.MailerProviderFactory.register("memory", (opt) => {
522
510
  return new import_neko_mailer.MemoryProvider();
523
511
  });
524
- var QueueTransportFactory = class _QueueTransportFactory {
525
- static {
526
- __name(this, "QueueTransportFactory");
527
- }
528
- static instance = new FlexibleFactory();
529
- static register(key, factory) {
530
- _QueueTransportFactory.instance.register(key, factory);
531
- }
532
- static create(key, ...args) {
533
- return _QueueTransportFactory.instance.create(key, ...args);
534
- }
535
- };
536
- QueueTransportFactory.register("database", (opt) => {
512
+ import_neko_queue2.QueueTransportFactory.register("database", (opt) => {
537
513
  let transport = new DatabaseTransport(opt);
538
514
  return new import_neko_queue.QueueConnection(transport);
539
515
  });
540
- QueueTransportFactory.register("memory", (opt) => {
516
+ import_neko_queue2.QueueTransportFactory.register("memory", (opt) => {
541
517
  let transport = new import_neko_queue2.MemoryTransport(opt);
542
518
  return new import_neko_queue.QueueConnection(transport);
543
519
  });
@@ -590,7 +566,10 @@ var scheduler = (0, import_neko_helper.createSingleton)(() => {
590
566
  var db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context2.ctx)().getOrThrow(["database", label]), "db");
591
567
  var storage = (0, import_neko_helper.createSingleton)((label = "default") => {
592
568
  let storage_config = import_neko_config.config.get(["storages", label].join("."));
593
- const provider = import_neko_storage2.StorageProviderFactory.create(storage_config.provider, storage_config.config);
569
+ const provider = import_neko_storage2.StorageProviderFactory.create(
570
+ storage_config.provider,
571
+ storage_config.config
572
+ );
594
573
  return new import_neko_storage2.Storage(provider);
595
574
  });
596
575
  var cli = (0, import_neko_helper.createSingleton)(() => {
@@ -647,7 +626,7 @@ var logger = (0, import_neko_helper.createSingleton)((label) => {
647
626
  });
648
627
  var mailer = (0, import_neko_helper.createSingleton)((label) => {
649
628
  const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
650
- const provider = MailerFactory.create(
629
+ const provider = import_neko_mailer2.MailerProviderFactory.create(
651
630
  mailer_config.provider,
652
631
  mailer_config.config
653
632
  );
@@ -659,7 +638,10 @@ var queue = (0, import_neko_helper.createSingleton)((label) => {
659
638
  if (!queue_config) {
660
639
  throw new Error(`Queue configuration for '${label}' not found`);
661
640
  }
662
- const provider = QueueTransportFactory.create(queue_config.provider, queue_config.config);
641
+ const provider = import_neko_queue3.QueueTransportFactory.create(
642
+ queue_config.provider,
643
+ queue_config.config
644
+ );
663
645
  const rc = new import_neko_queue3.QueueConnection(provider);
664
646
  return rc;
665
647
  });
@@ -675,12 +657,15 @@ var cache = (0, import_neko_helper.createSingleton)((label) => {
675
657
  return new import_neko_cache2.Cache(provider);
676
658
  });
677
659
 
660
+ // src/helper.mts
661
+ var helper_exports = {};
662
+ __reExport(helper_exports, require("@devbro/neko-helper"));
663
+
678
664
  // src/queue.mts
679
665
  var DatabaseTransport = class {
680
666
  static {
681
667
  __name(this, "DatabaseTransport");
682
668
  }
683
- activeIntervals = /* @__PURE__ */ new Set();
684
669
  config = {
685
670
  queue_table: "queue_messages",
686
671
  db_connection: "default",
@@ -689,14 +674,48 @@ var DatabaseTransport = class {
689
674
  message_limit: 10
690
675
  // messages per each fetch
691
676
  };
692
- constructor(config2) {
677
+ channels = /* @__PURE__ */ new Map();
678
+ messageQueues = [];
679
+ repeater;
680
+ processMessage = /* @__PURE__ */ __name(async () => {
681
+ const conn = db(this.config.db_connection);
682
+ try {
683
+ await conn.connect();
684
+ let q = conn.getQuery();
685
+ let messages = await q.table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
686
+ for (let msg of messages) {
687
+ try {
688
+ let callback = this.channels.get(msg.channel);
689
+ await callback(msg.message);
690
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
691
+ status: "processed",
692
+ updated_at: /* @__PURE__ */ new Date(),
693
+ last_tried_at: /* @__PURE__ */ new Date(),
694
+ retried_count: (msg.retried_count || 0) + 1
695
+ });
696
+ } catch (error) {
697
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
698
+ status: "failed",
699
+ last_tried_at: /* @__PURE__ */ new Date(),
700
+ retried_count: (msg.retried_count || 0) + 1,
701
+ process_message: error.message || "Error processing message"
702
+ });
703
+ }
704
+ }
705
+ } catch (error) {
706
+ logger().error("Error in DatabaseTransport listen interval:", {
707
+ error
708
+ });
709
+ } finally {
710
+ await conn.disconnect();
711
+ }
712
+ }, "processMessage");
713
+ constructor(config2 = {}) {
693
714
  this.config = { ...this.config, ...config2 };
694
- }
695
- setListenInterval(interval) {
696
- this.config.listen_interval = interval;
697
- }
698
- setMessageLimit(limit) {
699
- this.config.message_limit = limit;
715
+ this.repeater = (0, helper_exports.createRepeater)(
716
+ this.processMessage,
717
+ this.config.listen_interval * 1e3
718
+ );
700
719
  }
701
720
  async dispatch(channel, message) {
702
721
  const conn = db(this.config.db_connection);
@@ -714,50 +733,22 @@ var DatabaseTransport = class {
714
733
  created_at: /* @__PURE__ */ new Date(),
715
734
  updated_at: /* @__PURE__ */ new Date(),
716
735
  last_tried_at: null,
717
- process_message: ""
736
+ process_message: "",
737
+ retried_count: 0,
738
+ status: "pending"
718
739
  });
719
740
  } finally {
720
741
  await conn.disconnect();
721
742
  }
722
743
  }
723
- async listen(channel, callback) {
724
- return new Promise(async (resolve, reject) => {
725
- const intervalId = setInterval(async () => {
726
- const conn = db(this.config.db_connection);
727
- try {
728
- await conn.connect();
729
- let q = conn.getQuery();
730
- let messages = await q.table(this.config.queue_table).whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
731
- for (let msg of messages) {
732
- try {
733
- await callback(msg.message);
734
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
735
- processed: true,
736
- updated_at: /* @__PURE__ */ new Date()
737
- });
738
- } catch (error) {
739
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
740
- processed: false,
741
- last_tried_at: /* @__PURE__ */ new Date(),
742
- process_message: error.message || "Error processing message"
743
- });
744
- }
745
- }
746
- } catch (error) {
747
- this.activeIntervals.delete(intervalId);
748
- logger().error("Error in DatabaseTransport listen interval:", { error });
749
- } finally {
750
- await conn.disconnect();
751
- }
752
- }, this.config.listen_interval * 1e3);
753
- this.activeIntervals.add(intervalId);
754
- });
744
+ async registerListener(channel, callback) {
745
+ this.channels.set(channel, callback);
746
+ }
747
+ async startListening() {
748
+ this.repeater.start();
755
749
  }
756
750
  async stopListening() {
757
- for (const intervalId of this.activeIntervals) {
758
- clearInterval(intervalId);
759
- }
760
- this.activeIntervals.clear();
751
+ this.repeater.stop();
761
752
  }
762
753
  };
763
754
  // Annotate the CommonJS export names for ESM import in node:
package/dist/facades.mjs CHANGED
@@ -5,20 +5,19 @@ import { Scheduler } from "@devbro/neko-scheduler";
5
5
  import { createSingleton } from "@devbro/neko-helper";
6
6
  import { ctx, ctxSafe } from "@devbro/neko-context";
7
7
  import { Storage, StorageProviderFactory } from "@devbro/neko-storage";
8
- import { Mailer } from "@devbro/neko-mailer";
8
+ import {
9
+ Mailer,
10
+ MailerProviderFactory
11
+ } from "@devbro/neko-mailer";
9
12
  import { config } from "@devbro/neko-config";
10
13
  import { Cli } from "clipanion";
11
14
  import { HttpServer } from "./http.mjs";
12
15
  import { HttpError } from "./http.mjs";
13
16
  import * as yup from "yup";
14
17
  import { Logger } from "@devbro/neko-logger";
15
- import {
16
- CacheProviderFactory,
17
- MailerFactory,
18
- QueueTransportFactory
19
- } from "./factories.mjs";
18
+ import { CacheProviderFactory } from "./factories.mjs";
20
19
  import { Cache } from "@devbro/neko-cache";
21
- import { QueueConnection } from "@devbro/neko-queue";
20
+ import { QueueConnection, QueueTransportFactory } from "@devbro/neko-queue";
22
21
  const router = createSingleton(() => new Router());
23
22
  const scheduler = createSingleton(() => {
24
23
  const rc = new Scheduler();
@@ -34,7 +33,10 @@ const scheduler = createSingleton(() => {
34
33
  const db = /* @__PURE__ */ __name((label = "default") => ctx().getOrThrow(["database", label]), "db");
35
34
  const storage = createSingleton((label = "default") => {
36
35
  let storage_config = config.get(["storages", label].join("."));
37
- const provider = StorageProviderFactory.create(storage_config.provider, storage_config.config);
36
+ const provider = StorageProviderFactory.create(
37
+ storage_config.provider,
38
+ storage_config.config
39
+ );
38
40
  return new Storage(provider);
39
41
  });
40
42
  const cli = createSingleton(() => {
@@ -91,7 +93,7 @@ const logger = createSingleton((label) => {
91
93
  });
92
94
  const mailer = createSingleton((label) => {
93
95
  const mailer_config = config.get(["mailer", label].join("."));
94
- const provider = MailerFactory.create(
96
+ const provider = MailerProviderFactory.create(
95
97
  mailer_config.provider,
96
98
  mailer_config.config
97
99
  );
@@ -103,7 +105,10 @@ const queue = createSingleton((label) => {
103
105
  if (!queue_config) {
104
106
  throw new Error(`Queue configuration for '${label}' not found`);
105
107
  }
106
- const provider = QueueTransportFactory.create(queue_config.provider, queue_config.config);
108
+ const provider = QueueTransportFactory.create(
109
+ queue_config.provider,
110
+ queue_config.config
111
+ );
107
112
  const rc = new QueueConnection(provider);
108
113
  return rc;
109
114
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/facades.mts"],"sourcesContent":["import { Router } from \"./router.mjs\";\nimport { Schedule, Scheduler } from \"@devbro/neko-scheduler\";\nimport { createSingleton } from \"@devbro/neko-helper\";\nimport { ctx, ctxSafe } from \"@devbro/neko-context\";\nimport { Connection } from \"@devbro/neko-sql\";\nimport { Storage, StorageProviderFactory } from \"@devbro/neko-storage\";\nimport { Mailer, MailerProvider } from \"@devbro/neko-mailer\";\nimport { config } from \"@devbro/neko-config\";\nimport { Cli } from \"clipanion\";\nimport { HttpServer } from \"./http.mjs\";\nimport { HttpError } from \"./http.mjs\";\nimport * as yup from \"yup\";\nimport { Logger } from \"@devbro/neko-logger\";\nimport {\n CacheProviderFactory,\n MailerFactory,\n QueueTransportFactory,\n} from \"./factories.mjs\";\nimport { Cache, CacheProviderInterface } from \"@devbro/neko-cache\";\nimport { QueueConnection } from \"@devbro/neko-queue\";\n\nexport const router = createSingleton<Router>(() => new Router());\nexport const scheduler = createSingleton<Scheduler>(() => {\n const rc = new Scheduler();\n rc.setErrorHandler((err: any, job: Schedule) => {\n logger().error({\n msg: \"Scheduled job error\",\n err,\n job_name: job.getName(),\n });\n });\n return rc;\n});\nexport const db = (label = \"default\") =>\n ctx().getOrThrow<Connection>([\"database\", label]);\n\nexport const storage = createSingleton<Storage>((label: string = \"default\") => {\n let storage_config: any = config.get([\"storages\", label].join(\".\"));\n\n const provider = StorageProviderFactory.create(storage_config.provider, storage_config.config);\n\n return new Storage(provider);\n});\n\nexport const cli = createSingleton<Cli>(() => {\n const [node, app, ...args] = process.argv;\n return new Cli({\n binaryLabel: `My Application`,\n binaryName: `${node} ${app}`,\n binaryVersion: `1.0.0`,\n });\n});\n\nexport const httpServer = createSingleton<HttpServer>(() => {\n const server = new HttpServer();\n\n server.setErrorHandler(async (err: Error, req: any, res: any) => {\n if (err instanceof HttpError) {\n res.writeHead(err.statusCode, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ message: err.message, error: err.code }));\n logger().warn({ msg: \"HttpError: \" + err.message, err });\n return;\n } else if (err instanceof yup.ValidationError) {\n res.writeHead(422, { \"Content-Type\": \"application/json\" });\n const errs: any = {};\n err.inner.forEach((e: yup.ValidationError) => {\n // Sanitize sensitive fields\n const sanitizedParams = { ...e.params };\n if (/passw/i.test(e.path!)) {\n sanitizedParams.value = \"******\";\n sanitizedParams.originalValue = \"******\";\n }\n\n errs[e.path!] = {\n type: e.type,\n message: e.message,\n params: sanitizedParams,\n };\n });\n\n res.end(JSON.stringify({ message: \"validation error\", errors: errs }));\n logger().warn({ msg: \"ValidationError: \" + err.message, err });\n return;\n } else {\n logger().error({ msg: \"Error: \" + err.message, err });\n }\n res.writeHead(500, { \"Content-Type\": \"\" });\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n });\n server.setRouter(router());\n\n return server;\n});\n\nexport const logger = createSingleton<Logger>((label) => {\n const logger_config: any = config.get([\"loggers\", label].join(\".\"));\n const rc = new Logger(logger_config);\n rc.setExtrasFunction((message: any) => {\n message.requestId = ctxSafe()?.get(\"requestId\") || \"N/A\";\n return message;\n });\n\n return rc;\n});\n\nexport const mailer = createSingleton((label) => {\n const mailer_config: any = config.get([\"mailer\", label].join(\".\"));\n\n const provider: MailerProvider = MailerFactory.create(\n mailer_config.provider,\n mailer_config.config,\n );\n\n const rc = new Mailer(provider);\n return rc;\n});\n\nexport const queue = createSingleton((label) => {\n const queue_config: any = config.get([\"queues\", label].join(\".\"));\n if (!queue_config) {\n throw new Error(`Queue configuration for '${label}' not found`);\n }\n const provider = QueueTransportFactory.create(queue_config.provider, queue_config.config);\n const rc = new QueueConnection(provider);\n return rc;\n});\n\nexport const cache = createSingleton((label) => {\n const cache_config: any = config.get([\"caches\", label].join(\".\"));\n if (!cache_config) {\n throw new Error(`Cache configuration for '${label}' not found`);\n }\n const provider = CacheProviderFactory.create(\n cache_config.provider,\n cache_config.config,\n );\n\n return new Cache(provider);\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/facades.mts"],"sourcesContent":["import { Router } from \"./router.mjs\";\nimport { Schedule, Scheduler } from \"@devbro/neko-scheduler\";\nimport { createSingleton } from \"@devbro/neko-helper\";\nimport { ctx, ctxSafe } from \"@devbro/neko-context\";\nimport { Connection } from \"@devbro/neko-sql\";\nimport { Storage, StorageProviderFactory } from \"@devbro/neko-storage\";\nimport {\n Mailer,\n MailerProvider,\n MailerProviderFactory,\n} from \"@devbro/neko-mailer\";\nimport { config } from \"@devbro/neko-config\";\nimport { Cli } from \"clipanion\";\nimport { HttpServer } from \"./http.mjs\";\nimport { HttpError } from \"./http.mjs\";\nimport * as yup from \"yup\";\nimport { Logger } from \"@devbro/neko-logger\";\nimport { CacheProviderFactory } from \"./factories.mjs\";\nimport { Cache } from \"@devbro/neko-cache\";\nimport { QueueConnection, QueueTransportFactory } from \"@devbro/neko-queue\";\n\nexport const router = createSingleton<Router>(() => new Router());\nexport const scheduler = createSingleton<Scheduler>(() => {\n const rc = new Scheduler();\n rc.setErrorHandler((err: any, job: Schedule) => {\n logger().error({\n msg: \"Scheduled job error\",\n err,\n job_name: job.getName(),\n });\n });\n return rc;\n});\nexport const db = (label = \"default\") =>\n ctx().getOrThrow<Connection>([\"database\", label]);\n\nexport const storage = createSingleton<Storage>((label: string = \"default\") => {\n let storage_config: any = config.get([\"storages\", label].join(\".\"));\n\n const provider = StorageProviderFactory.create(\n storage_config.provider,\n storage_config.config,\n );\n\n return new Storage(provider);\n});\n\nexport const cli = createSingleton<Cli>(() => {\n const [node, app, ...args] = process.argv;\n return new Cli({\n binaryLabel: `My Application`,\n binaryName: `${node} ${app}`,\n binaryVersion: `1.0.0`,\n });\n});\n\nexport const httpServer = createSingleton<HttpServer>(() => {\n const server = new HttpServer();\n\n server.setErrorHandler(async (err: Error, req: any, res: any) => {\n if (err instanceof HttpError) {\n res.writeHead(err.statusCode, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ message: err.message, error: err.code }));\n logger().warn({ msg: \"HttpError: \" + err.message, err });\n return;\n } else if (err instanceof yup.ValidationError) {\n res.writeHead(422, { \"Content-Type\": \"application/json\" });\n const errs: any = {};\n err.inner.forEach((e: yup.ValidationError) => {\n // Sanitize sensitive fields\n const sanitizedParams = { ...e.params };\n if (/passw/i.test(e.path!)) {\n sanitizedParams.value = \"******\";\n sanitizedParams.originalValue = \"******\";\n }\n\n errs[e.path!] = {\n type: e.type,\n message: e.message,\n params: sanitizedParams,\n };\n });\n\n res.end(JSON.stringify({ message: \"validation error\", errors: errs }));\n logger().warn({ msg: \"ValidationError: \" + err.message, err });\n return;\n } else {\n logger().error({ msg: \"Error: \" + err.message, err });\n }\n res.writeHead(500, { \"Content-Type\": \"\" });\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n });\n server.setRouter(router());\n\n return server;\n});\n\nexport const logger = createSingleton<Logger>((label) => {\n const logger_config: any = config.get([\"loggers\", label].join(\".\"));\n const rc = new Logger(logger_config);\n rc.setExtrasFunction((message: any) => {\n message.requestId = ctxSafe()?.get(\"requestId\") || \"N/A\";\n return message;\n });\n\n return rc;\n});\n\nexport const mailer = createSingleton((label) => {\n const mailer_config: any = config.get([\"mailer\", label].join(\".\"));\n\n const provider: MailerProvider = MailerProviderFactory.create(\n mailer_config.provider,\n mailer_config.config,\n );\n\n const rc = new Mailer(provider);\n return rc;\n});\n\nexport const queue = createSingleton((label) => {\n const queue_config: any = config.get([\"queues\", label].join(\".\"));\n if (!queue_config) {\n throw new Error(`Queue configuration for '${label}' not found`);\n }\n const provider = QueueTransportFactory.create(\n queue_config.provider,\n queue_config.config,\n );\n const rc = new QueueConnection(provider);\n return rc;\n});\n\nexport const cache = createSingleton((label) => {\n const cache_config: any = config.get([\"caches\", label].join(\".\"));\n if (!cache_config) {\n throw new Error(`Cache configuration for '${label}' not found`);\n }\n const provider = CacheProviderFactory.create(\n cache_config.provider,\n cache_config.config,\n );\n\n return new Cache(provider);\n});\n"],"mappings":"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","names":[]}
@@ -1,5 +1,3 @@
1
- import { MailerProvider } from '@devbro/neko-mailer';
2
- import { QueueConnection, QueueTransportInterface } from '@devbro/neko-queue';
3
1
  import { CacheProviderInterface } from '@devbro/neko-cache';
4
2
 
5
3
  declare class FlexibleFactory<T> {
@@ -7,20 +5,10 @@ declare class FlexibleFactory<T> {
7
5
  register<T>(key: string, ctor: (...args: any[]) => T): void;
8
6
  create<T>(key: string, ...args: any[]): T;
9
7
  }
10
- declare class MailerFactory {
11
- static instance: FlexibleFactory<MailerProvider>;
12
- static register<T>(key: string, factory: (...args: any[]) => MailerProvider): void;
13
- static create<T>(key: string, ...args: any[]): MailerProvider;
14
- }
15
- declare class QueueTransportFactory {
16
- static instance: FlexibleFactory<QueueConnection<any>>;
17
- static register<T>(key: string, factory: (...args: any[]) => T): void;
18
- static create<T>(key: string, ...args: any[]): QueueTransportInterface;
19
- }
20
8
  declare class CacheProviderFactory {
21
9
  static instance: FlexibleFactory<CacheProviderInterface>;
22
10
  static register(key: string, factory: (...args: any[]) => CacheProviderInterface): void;
23
11
  static create<T>(key: string, ...args: any[]): CacheProviderInterface;
24
12
  }
25
13
 
26
- export { CacheProviderFactory, FlexibleFactory, MailerFactory, QueueTransportFactory };
14
+ export { CacheProviderFactory, FlexibleFactory };
@@ -4,11 +4,12 @@ import {
4
4
  FunctionProvider,
5
5
  SESProvider,
6
6
  SMTPProvider,
7
- MemoryProvider
7
+ MemoryProvider,
8
+ MailerProviderFactory
8
9
  } from "@devbro/neko-mailer";
9
10
  import { logger } from "./facades.mjs";
10
11
  import { QueueConnection } from "@devbro/neko-queue";
11
- import { MemoryTransport } from "@devbro/neko-queue";
12
+ import { MemoryTransport, QueueTransportFactory } from "@devbro/neko-queue";
12
13
  import { DatabaseTransport } from "./queue.mjs";
13
14
  import {
14
15
  MemoryCacheProvider,
@@ -16,7 +17,11 @@ import {
16
17
  FileCacheProvider,
17
18
  DisabledCacheProvider
18
19
  } from "@devbro/neko-cache";
19
- import { AWSS3StorageProvider, LocalStorageProvider, StorageProviderFactory } from "@devbro/neko-storage";
20
+ import {
21
+ AWSS3StorageProvider,
22
+ LocalStorageProvider,
23
+ StorageProviderFactory
24
+ } from "@devbro/neko-storage";
20
25
  class FlexibleFactory {
21
26
  static {
22
27
  __name(this, "FlexibleFactory");
@@ -33,19 +38,7 @@ class FlexibleFactory {
33
38
  return ctor(...args);
34
39
  }
35
40
  }
36
- class MailerFactory {
37
- static {
38
- __name(this, "MailerFactory");
39
- }
40
- static instance = new FlexibleFactory();
41
- static register(key, factory) {
42
- MailerFactory.instance.register(key, factory);
43
- }
44
- static create(key, ...args) {
45
- return MailerFactory.instance.create(key, ...args);
46
- }
47
- }
48
- MailerFactory.register("logger", (opt) => {
41
+ MailerProviderFactory.register("logger", (opt) => {
49
42
  return new FunctionProvider((mail) => {
50
43
  logger().info({
51
44
  msg: "Sending email",
@@ -53,27 +46,15 @@ MailerFactory.register("logger", (opt) => {
53
46
  });
54
47
  });
55
48
  });
56
- MailerFactory.register("ses", (opt) => {
49
+ MailerProviderFactory.register("ses", (opt) => {
57
50
  return new SESProvider(opt);
58
51
  });
59
- MailerFactory.register("smtp", (opt) => {
52
+ MailerProviderFactory.register("smtp", (opt) => {
60
53
  return new SMTPProvider(opt);
61
54
  });
62
- MailerFactory.register("memory", (opt) => {
55
+ MailerProviderFactory.register("memory", (opt) => {
63
56
  return new MemoryProvider();
64
57
  });
65
- class QueueTransportFactory {
66
- static {
67
- __name(this, "QueueTransportFactory");
68
- }
69
- static instance = new FlexibleFactory();
70
- static register(key, factory) {
71
- QueueTransportFactory.instance.register(key, factory);
72
- }
73
- static create(key, ...args) {
74
- return QueueTransportFactory.instance.create(key, ...args);
75
- }
76
- }
77
58
  QueueTransportFactory.register("database", (opt) => {
78
59
  let transport = new DatabaseTransport(opt);
79
60
  return new QueueConnection(transport);
@@ -114,8 +95,6 @@ StorageProviderFactory.register("s3", (opt) => {
114
95
  });
115
96
  export {
116
97
  CacheProviderFactory,
117
- FlexibleFactory,
118
- MailerFactory,
119
- QueueTransportFactory
98
+ FlexibleFactory
120
99
  };
121
100
  //# sourceMappingURL=factories.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/factories.mts"],"sourcesContent":["import {\n Mailer,\n Mailable,\n MailerProvider,\n FunctionProvider,\n SESProvider,\n SMTPProvider,\n MemoryProvider,\n} from \"@devbro/neko-mailer\";\nimport { logger } from \"./facades.mjs\";\nimport { QueueConnection, QueueTransportInterface } from \"@devbro/neko-queue\";\nimport { MemoryTransport } from \"@devbro/neko-queue\";\nimport { DatabaseTransport } from \"./queue.mjs\";\nimport {\n CacheProviderInterface,\n MemoryCacheProvider,\n RedisCacheProvider,\n FileCacheProvider,\n DisabledCacheProvider,\n} from \"@devbro/neko-cache\";\nimport { AWSS3StorageProvider, LocalStorageProvider, StorageProviderFactory } from \"@devbro/neko-storage\";\n\nexport class FlexibleFactory<T> {\n registry: Map<string, any> = new Map();\n\n register<T>(key: string, ctor: (...args: any[]) => T) {\n this.registry.set(key, ctor);\n }\n\n create<T>(key: string, ...args: any[]): T {\n const ctor = this.registry.get(key);\n if (!ctor) {\n throw new Error(`No factory registered for key: ${key}`);\n }\n return ctor(...args);\n }\n}\n\nexport class MailerFactory {\n static instance: FlexibleFactory<MailerProvider> =\n new FlexibleFactory<MailerProvider>();\n\n static register<T>(\n key: string,\n factory: (...args: any[]) => MailerProvider,\n ): void {\n MailerFactory.instance.register(key, factory);\n }\n\n static create<T>(key: string, ...args: any[]): MailerProvider {\n return MailerFactory.instance.create(key, ...args);\n }\n}\n\nMailerFactory.register(\"logger\", (opt) => {\n return new FunctionProvider((mail: Mailable) => {\n logger().info({\n msg: \"Sending email\",\n mail,\n });\n });\n});\n\nMailerFactory.register(\"ses\", (opt) => {\n return new SESProvider(opt);\n});\n\nMailerFactory.register(\"smtp\", (opt) => {\n return new SMTPProvider(opt);\n});\n\nMailerFactory.register(\"memory\", (opt) => {\n return new MemoryProvider();\n});\n\nexport class QueueTransportFactory {\n static instance: FlexibleFactory<QueueConnection<any>> = new FlexibleFactory<\n QueueConnection<any>\n >();\n\n static register<T>(key: string, factory: (...args: any[]) => T): void {\n QueueTransportFactory.instance.register(key, factory);\n }\n\n static create<T>(key: string, ...args: any[]): QueueTransportInterface {\n return QueueTransportFactory.instance.create(key, ...args);\n }\n}\n\nQueueTransportFactory.register(\"database\", (opt) => {\n let transport = new DatabaseTransport(opt);\n return new QueueConnection(transport);\n});\n\nQueueTransportFactory.register(\"memory\", (opt) => {\n let transport = new MemoryTransport(opt);\n return new QueueConnection(transport);\n});\n\n// CACHE\nexport class CacheProviderFactory {\n static instance: FlexibleFactory<CacheProviderInterface> =\n new FlexibleFactory<CacheProviderInterface>();\n\n static register(\n key: string,\n factory: (...args: any[]) => CacheProviderInterface,\n ): void {\n CacheProviderFactory.instance.register(key, factory);\n }\n\n static create<T>(key: string, ...args: any[]): CacheProviderInterface {\n return CacheProviderFactory.instance.create(key, ...args);\n }\n}\n\nCacheProviderFactory.register(\"memory\", (opt) => {\n return new MemoryCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"redis\", (opt) => {\n return new RedisCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"file\", (opt) => {\n return new FileCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"disabled\", (opt) => {\n return new DisabledCacheProvider();\n});\n\nStorageProviderFactory.register(\"local\", (opt) => {\n return new LocalStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"s3\", (opt) => {\n return new AWSS3StorageProvider(opt);\n});"],"mappings":";;AAAA;AAAA,EAIE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,uBAAgD;AACzD,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB,sBAAsB,8BAA8B;AAE5E,MAAM,gBAAmB;AAAA,EAtBhC,OAsBgC;AAAA;AAAA;AAAA,EAC9B,WAA6B,oBAAI,IAAI;AAAA,EAErC,SAAY,KAAa,MAA6B;AACpD,SAAK,SAAS,IAAI,KAAK,IAAI;AAAA,EAC7B;AAAA,EAEA,OAAU,QAAgB,MAAgB;AACxC,UAAM,OAAO,KAAK,SAAS,IAAI,GAAG;AAClC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,kCAAkC,GAAG,EAAE;AAAA,IACzD;AACA,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AACF;AAEO,MAAM,cAAc;AAAA,EAtC3B,OAsC2B;AAAA;AAAA;AAAA,EACzB,OAAO,WACL,IAAI,gBAAgC;AAAA,EAEtC,OAAO,SACL,KACA,SACM;AACN,kBAAc,SAAS,SAAS,KAAK,OAAO;AAAA,EAC9C;AAAA,EAEA,OAAO,OAAU,QAAgB,MAA6B;AAC5D,WAAO,cAAc,SAAS,OAAO,KAAK,GAAG,IAAI;AAAA,EACnD;AACF;AAEA,cAAc,SAAS,UAAU,CAAC,QAAQ;AACxC,SAAO,IAAI,iBAAiB,CAAC,SAAmB;AAC9C,WAAO,EAAE,KAAK;AAAA,MACZ,KAAK;AAAA,MACL;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH,CAAC;AAED,cAAc,SAAS,OAAO,CAAC,QAAQ;AACrC,SAAO,IAAI,YAAY,GAAG;AAC5B,CAAC;AAED,cAAc,SAAS,QAAQ,CAAC,QAAQ;AACtC,SAAO,IAAI,aAAa,GAAG;AAC7B,CAAC;AAED,cAAc,SAAS,UAAU,CAAC,QAAQ;AACxC,SAAO,IAAI,eAAe;AAC5B,CAAC;AAEM,MAAM,sBAAsB;AAAA,EA3EnC,OA2EmC;AAAA;AAAA;AAAA,EACjC,OAAO,WAAkD,IAAI,gBAE3D;AAAA,EAEF,OAAO,SAAY,KAAa,SAAsC;AACpE,0BAAsB,SAAS,SAAS,KAAK,OAAO;AAAA,EACtD;AAAA,EAEA,OAAO,OAAU,QAAgB,MAAsC;AACrE,WAAO,sBAAsB,SAAS,OAAO,KAAK,GAAG,IAAI;AAAA,EAC3D;AACF;AAEA,sBAAsB,SAAS,YAAY,CAAC,QAAQ;AAClD,MAAI,YAAY,IAAI,kBAAkB,GAAG;AACzC,SAAO,IAAI,gBAAgB,SAAS;AACtC,CAAC;AAED,sBAAsB,SAAS,UAAU,CAAC,QAAQ;AAChD,MAAI,YAAY,IAAI,gBAAgB,GAAG;AACvC,SAAO,IAAI,gBAAgB,SAAS;AACtC,CAAC;AAGM,MAAM,qBAAqB;AAAA,EApGlC,OAoGkC;AAAA;AAAA;AAAA,EAChC,OAAO,WACL,IAAI,gBAAwC;AAAA,EAE9C,OAAO,SACL,KACA,SACM;AACN,yBAAqB,SAAS,SAAS,KAAK,OAAO;AAAA,EACrD;AAAA,EAEA,OAAO,OAAU,QAAgB,MAAqC;AACpE,WAAO,qBAAqB,SAAS,OAAO,KAAK,GAAG,IAAI;AAAA,EAC1D;AACF;AAEA,qBAAqB,SAAS,UAAU,CAAC,QAAQ;AAC/C,SAAO,IAAI,oBAAoB,GAAG;AACpC,CAAC;AAED,qBAAqB,SAAS,SAAS,CAAC,QAAQ;AAC9C,SAAO,IAAI,mBAAmB,GAAG;AACnC,CAAC;AAED,qBAAqB,SAAS,QAAQ,CAAC,QAAQ;AAC7C,SAAO,IAAI,kBAAkB,GAAG;AAClC,CAAC;AAED,qBAAqB,SAAS,YAAY,CAAC,QAAQ;AACjD,SAAO,IAAI,sBAAsB;AACnC,CAAC;AAED,uBAAuB,SAAS,SAAS,CAAC,QAAQ;AAChD,SAAO,IAAI,qBAAqB,GAAG;AACrC,CAAC;AAED,uBAAuB,SAAS,MAAM,CAAC,QAAQ;AAC7C,SAAO,IAAI,qBAAqB,GAAG;AACrC,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/factories.mts"],"sourcesContent":["import {\n Mailer,\n Mailable,\n MailerProvider,\n FunctionProvider,\n SESProvider,\n SMTPProvider,\n MemoryProvider,\n MailerProviderFactory,\n} from \"@devbro/neko-mailer\";\nimport { logger } from \"./facades.mjs\";\nimport { QueueConnection, QueueTransportInterface } from \"@devbro/neko-queue\";\nimport { MemoryTransport, QueueTransportFactory } from \"@devbro/neko-queue\";\nimport { DatabaseTransport } from \"./queue.mjs\";\nimport {\n CacheProviderInterface,\n MemoryCacheProvider,\n RedisCacheProvider,\n FileCacheProvider,\n DisabledCacheProvider,\n} from \"@devbro/neko-cache\";\nimport {\n AWSS3StorageProvider,\n LocalStorageProvider,\n StorageProviderFactory,\n} from \"@devbro/neko-storage\";\n\nexport class FlexibleFactory<T> {\n registry: Map<string, any> = new Map();\n\n register<T>(key: string, ctor: (...args: any[]) => T) {\n this.registry.set(key, ctor);\n }\n\n create<T>(key: string, ...args: any[]): T {\n const ctor = this.registry.get(key);\n if (!ctor) {\n throw new Error(`No factory registered for key: ${key}`);\n }\n return ctor(...args);\n }\n}\n\nMailerProviderFactory.register(\"logger\", (opt) => {\n return new FunctionProvider((mail: Mailable) => {\n logger().info({\n msg: \"Sending email\",\n mail,\n });\n });\n});\n\nMailerProviderFactory.register(\"ses\", (opt) => {\n return new SESProvider(opt);\n});\n\nMailerProviderFactory.register(\"smtp\", (opt) => {\n return new SMTPProvider(opt);\n});\n\nMailerProviderFactory.register(\"memory\", (opt) => {\n return new MemoryProvider();\n});\n\nQueueTransportFactory.register(\"database\", (opt) => {\n let transport = new DatabaseTransport(opt);\n return new QueueConnection(transport);\n});\n\nQueueTransportFactory.register(\"memory\", (opt) => {\n let transport = new MemoryTransport(opt);\n return new QueueConnection(transport);\n});\n\n// CACHE\nexport class CacheProviderFactory {\n static instance: FlexibleFactory<CacheProviderInterface> =\n new FlexibleFactory<CacheProviderInterface>();\n\n static register(\n key: string,\n factory: (...args: any[]) => CacheProviderInterface,\n ): void {\n CacheProviderFactory.instance.register(key, factory);\n }\n\n static create<T>(key: string, ...args: any[]): CacheProviderInterface {\n return CacheProviderFactory.instance.create(key, ...args);\n }\n}\n\nCacheProviderFactory.register(\"memory\", (opt) => {\n return new MemoryCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"redis\", (opt) => {\n return new RedisCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"file\", (opt) => {\n return new FileCacheProvider(opt);\n});\n\nCacheProviderFactory.register(\"disabled\", (opt) => {\n return new DisabledCacheProvider();\n});\n\nStorageProviderFactory.register(\"local\", (opt) => {\n return new LocalStorageProvider(opt);\n});\n\nStorageProviderFactory.register(\"s3\", (opt) => {\n return new AWSS3StorageProvider(opt);\n});\n"],"mappings":";;AAAA;AAAA,EAIE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,uBAAgD;AACzD,SAAS,iBAAiB,6BAA6B;AACvD,SAAS,yBAAyB;AAClC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,gBAAmB;AAAA,EA3BhC,OA2BgC;AAAA;AAAA;AAAA,EAC9B,WAA6B,oBAAI,IAAI;AAAA,EAErC,SAAY,KAAa,MAA6B;AACpD,SAAK,SAAS,IAAI,KAAK,IAAI;AAAA,EAC7B;AAAA,EAEA,OAAU,QAAgB,MAAgB;AACxC,UAAM,OAAO,KAAK,SAAS,IAAI,GAAG;AAClC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,kCAAkC,GAAG,EAAE;AAAA,IACzD;AACA,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AACF;AAEA,sBAAsB,SAAS,UAAU,CAAC,QAAQ;AAChD,SAAO,IAAI,iBAAiB,CAAC,SAAmB;AAC9C,WAAO,EAAE,KAAK;AAAA,MACZ,KAAK;AAAA,MACL;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH,CAAC;AAED,sBAAsB,SAAS,OAAO,CAAC,QAAQ;AAC7C,SAAO,IAAI,YAAY,GAAG;AAC5B,CAAC;AAED,sBAAsB,SAAS,QAAQ,CAAC,QAAQ;AAC9C,SAAO,IAAI,aAAa,GAAG;AAC7B,CAAC;AAED,sBAAsB,SAAS,UAAU,CAAC,QAAQ;AAChD,SAAO,IAAI,eAAe;AAC5B,CAAC;AAED,sBAAsB,SAAS,YAAY,CAAC,QAAQ;AAClD,MAAI,YAAY,IAAI,kBAAkB,GAAG;AACzC,SAAO,IAAI,gBAAgB,SAAS;AACtC,CAAC;AAED,sBAAsB,SAAS,UAAU,CAAC,QAAQ;AAChD,MAAI,YAAY,IAAI,gBAAgB,GAAG;AACvC,SAAO,IAAI,gBAAgB,SAAS;AACtC,CAAC;AAGM,MAAM,qBAAqB;AAAA,EA3ElC,OA2EkC;AAAA;AAAA;AAAA,EAChC,OAAO,WACL,IAAI,gBAAwC;AAAA,EAE9C,OAAO,SACL,KACA,SACM;AACN,yBAAqB,SAAS,SAAS,KAAK,OAAO;AAAA,EACrD;AAAA,EAEA,OAAO,OAAU,QAAgB,MAAqC;AACpE,WAAO,qBAAqB,SAAS,OAAO,KAAK,GAAG,IAAI;AAAA,EAC1D;AACF;AAEA,qBAAqB,SAAS,UAAU,CAAC,QAAQ;AAC/C,SAAO,IAAI,oBAAoB,GAAG;AACpC,CAAC;AAED,qBAAqB,SAAS,SAAS,CAAC,QAAQ;AAC9C,SAAO,IAAI,mBAAmB,GAAG;AACnC,CAAC;AAED,qBAAqB,SAAS,QAAQ,CAAC,QAAQ;AAC7C,SAAO,IAAI,kBAAkB,GAAG;AAClC,CAAC;AAED,qBAAqB,SAAS,YAAY,CAAC,QAAQ;AACjD,SAAO,IAAI,sBAAsB;AACnC,CAAC;AAED,uBAAuB,SAAS,SAAS,CAAC,QAAQ;AAChD,SAAO,IAAI,qBAAqB,GAAG;AACrC,CAAC;AAED,uBAAuB,SAAS,MAAM,CAAC,QAAQ;AAC7C,SAAO,IAAI,qBAAqB,GAAG;AACrC,CAAC;","names":[]}
package/dist/queue.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { QueueTransportInterface } from '@devbro/neko-queue';
2
2
  export * from '@devbro/neko-queue';
3
+ import { createRepeater } from '@devbro/neko-helper';
3
4
 
4
5
  type DatabaseTransportConfig = {
5
6
  queue_table: string;
@@ -8,13 +9,18 @@ type DatabaseTransportConfig = {
8
9
  message_limit: number;
9
10
  };
10
11
  declare class DatabaseTransport implements QueueTransportInterface {
11
- private activeIntervals;
12
12
  private config;
13
- constructor(config: Partial<DatabaseTransportConfig>);
14
- setListenInterval(interval: number): void;
15
- setMessageLimit(limit: number): void;
13
+ channels: Map<string, (message: string) => Promise<void>>;
14
+ messageQueues: {
15
+ channel: string;
16
+ message: string;
17
+ }[];
18
+ repeater: ReturnType<typeof createRepeater>;
19
+ processMessage: () => Promise<void>;
20
+ constructor(config?: Partial<DatabaseTransportConfig>);
16
21
  dispatch(channel: string, message: string): Promise<void>;
17
- listen(channel: string, callback: (message: string) => Promise<void>): Promise<void>;
22
+ registerListener(channel: string, callback: (message: string) => Promise<void>): Promise<void>;
23
+ startListening(): Promise<void>;
18
24
  stopListening(): Promise<void>;
19
25
  }
20
26
 
package/dist/queue.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
  export * from "@devbro/neko-queue";
4
- import { db, logger } from "./facades.mts";
4
+ import { db, logger } from "./facades.mjs";
5
+ import { createRepeater } from "./helper.mts";
5
6
  class DatabaseTransport {
6
7
  static {
7
8
  __name(this, "DatabaseTransport");
8
9
  }
9
- activeIntervals = /* @__PURE__ */ new Set();
10
10
  config = {
11
11
  queue_table: "queue_messages",
12
12
  db_connection: "default",
@@ -15,14 +15,48 @@ class DatabaseTransport {
15
15
  message_limit: 10
16
16
  // messages per each fetch
17
17
  };
18
- constructor(config) {
18
+ channels = /* @__PURE__ */ new Map();
19
+ messageQueues = [];
20
+ repeater;
21
+ processMessage = /* @__PURE__ */ __name(async () => {
22
+ const conn = db(this.config.db_connection);
23
+ try {
24
+ await conn.connect();
25
+ let q = conn.getQuery();
26
+ let messages = await q.table(this.config.queue_table).whereOp("channel", "in", Array.from(this.channels.keys())).whereOp("status", "in", ["pending", "failed"]).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
27
+ for (let msg of messages) {
28
+ try {
29
+ let callback = this.channels.get(msg.channel);
30
+ await callback(msg.message);
31
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
32
+ status: "processed",
33
+ updated_at: /* @__PURE__ */ new Date(),
34
+ last_tried_at: /* @__PURE__ */ new Date(),
35
+ retried_count: (msg.retried_count || 0) + 1
36
+ });
37
+ } catch (error) {
38
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
39
+ status: "failed",
40
+ last_tried_at: /* @__PURE__ */ new Date(),
41
+ retried_count: (msg.retried_count || 0) + 1,
42
+ process_message: error.message || "Error processing message"
43
+ });
44
+ }
45
+ }
46
+ } catch (error) {
47
+ logger().error("Error in DatabaseTransport listen interval:", {
48
+ error
49
+ });
50
+ } finally {
51
+ await conn.disconnect();
52
+ }
53
+ }, "processMessage");
54
+ constructor(config = {}) {
19
55
  this.config = { ...this.config, ...config };
20
- }
21
- setListenInterval(interval) {
22
- this.config.listen_interval = interval;
23
- }
24
- setMessageLimit(limit) {
25
- this.config.message_limit = limit;
56
+ this.repeater = createRepeater(
57
+ this.processMessage,
58
+ this.config.listen_interval * 1e3
59
+ );
26
60
  }
27
61
  async dispatch(channel, message) {
28
62
  const conn = db(this.config.db_connection);
@@ -40,50 +74,22 @@ class DatabaseTransport {
40
74
  created_at: /* @__PURE__ */ new Date(),
41
75
  updated_at: /* @__PURE__ */ new Date(),
42
76
  last_tried_at: null,
43
- process_message: ""
77
+ process_message: "",
78
+ retried_count: 0,
79
+ status: "pending"
44
80
  });
45
81
  } finally {
46
82
  await conn.disconnect();
47
83
  }
48
84
  }
49
- async listen(channel, callback) {
50
- return new Promise(async (resolve, reject) => {
51
- const intervalId = setInterval(async () => {
52
- const conn = db(this.config.db_connection);
53
- try {
54
- await conn.connect();
55
- let q = conn.getQuery();
56
- let messages = await q.table(this.config.queue_table).whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
57
- for (let msg of messages) {
58
- try {
59
- await callback(msg.message);
60
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
61
- processed: true,
62
- updated_at: /* @__PURE__ */ new Date()
63
- });
64
- } catch (error) {
65
- await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
66
- processed: false,
67
- last_tried_at: /* @__PURE__ */ new Date(),
68
- process_message: error.message || "Error processing message"
69
- });
70
- }
71
- }
72
- } catch (error) {
73
- this.activeIntervals.delete(intervalId);
74
- logger().error("Error in DatabaseTransport listen interval:", { error });
75
- } finally {
76
- await conn.disconnect();
77
- }
78
- }, this.config.listen_interval * 1e3);
79
- this.activeIntervals.add(intervalId);
80
- });
85
+ async registerListener(channel, callback) {
86
+ this.channels.set(channel, callback);
87
+ }
88
+ async startListening() {
89
+ this.repeater.start();
81
90
  }
82
91
  async stopListening() {
83
- for (const intervalId of this.activeIntervals) {
84
- clearInterval(intervalId);
85
- }
86
- this.activeIntervals.clear();
92
+ this.repeater.stop();
87
93
  }
88
94
  }
89
95
  export {