@holo-js/queue 0.2.5 → 0.3.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.
package/dist/index.mjs CHANGED
@@ -1,3 +1,17 @@
1
+ import {
2
+ DEFAULT_DATABASE_QUEUE_TABLE,
3
+ DEFAULT_FAILED_JOBS_CONNECTION,
4
+ DEFAULT_FAILED_JOBS_TABLE,
5
+ DEFAULT_QUEUE_BLOCK_FOR,
6
+ DEFAULT_QUEUE_CONNECTION,
7
+ DEFAULT_QUEUE_NAME,
8
+ DEFAULT_QUEUE_RETRY_AFTER,
9
+ DEFAULT_QUEUE_SLEEP,
10
+ holoQueueDefaults,
11
+ normalizeQueueConfig,
12
+ queueInternals
13
+ } from "./chunk-5MPOVBVE.mjs";
14
+
1
15
  // src/contracts.ts
2
16
  function getQueueJobDispatcher() {
3
17
  return globalThis.__holoQueueJobDispatcher__;
@@ -229,247 +243,6 @@ var queueJobInternals = {
229
243
  setQueueJobSyncDispatcher
230
244
  };
231
245
 
232
- // src/config.ts
233
- var DEFAULT_QUEUE_CONNECTION = "sync";
234
- var DEFAULT_QUEUE_NAME = "default";
235
- var DEFAULT_QUEUE_RETRY_AFTER = 90;
236
- var DEFAULT_QUEUE_BLOCK_FOR = 5;
237
- var DEFAULT_QUEUE_SLEEP = 1;
238
- var DEFAULT_FAILED_JOBS_CONNECTION = "default";
239
- var DEFAULT_FAILED_JOBS_TABLE = "failed_jobs";
240
- var DEFAULT_DATABASE_QUEUE_TABLE = "jobs";
241
- var DEFAULT_REDIS_HOST = "127.0.0.1";
242
- var DEFAULT_REDIS_PORT = 6379;
243
- var DEFAULT_REDIS_DB = 0;
244
- var DEFAULT_QUEUE_CONFIG = Object.freeze({
245
- default: DEFAULT_QUEUE_CONNECTION,
246
- failed: Object.freeze({
247
- driver: "database",
248
- connection: DEFAULT_FAILED_JOBS_CONNECTION,
249
- table: DEFAULT_FAILED_JOBS_TABLE
250
- }),
251
- connections: Object.freeze({
252
- [DEFAULT_QUEUE_CONNECTION]: Object.freeze({
253
- name: DEFAULT_QUEUE_CONNECTION,
254
- driver: "sync",
255
- queue: DEFAULT_QUEUE_NAME
256
- })
257
- })
258
- });
259
- function parseInteger(value, fallback, label, options = {}) {
260
- if (typeof value === "undefined") {
261
- return fallback;
262
- }
263
- const normalized = typeof value === "number" ? value : value.trim();
264
- if (typeof normalized === "string" && !/^[+-]?\d+$/.test(normalized)) {
265
- throw new Error(`[Holo Queue] ${label} must be an integer.`);
266
- }
267
- const integer = typeof normalized === "number" ? normalized : Number(normalized);
268
- if (!Number.isInteger(integer)) {
269
- throw new Error(`[Holo Queue] ${label} must be an integer.`);
270
- }
271
- if (typeof options.minimum === "number" && integer < options.minimum) {
272
- throw new Error(`[Holo Queue] ${label} must be greater than or equal to ${options.minimum}.`);
273
- }
274
- return integer;
275
- }
276
- function normalizeConnectionName(value, label) {
277
- const normalized = value?.trim();
278
- if (!normalized) {
279
- throw new Error(`[Holo Queue] ${label} must be a non-empty string.`);
280
- }
281
- return normalized;
282
- }
283
- function normalizeQueueName(value) {
284
- return value?.trim() || DEFAULT_QUEUE_NAME;
285
- }
286
- function normalizeOptionalRedisString(value) {
287
- return value?.trim() || void 0;
288
- }
289
- function normalizeSyncConnection(name, config) {
290
- return Object.freeze({
291
- name,
292
- driver: "sync",
293
- queue: normalizeQueueName(config.queue)
294
- });
295
- }
296
- function resolveSharedRedisConnection(redisConfig, connectionName) {
297
- const resolvedConnection = redisConfig.connections[connectionName];
298
- if (!resolvedConnection) {
299
- const availableConnections = Object.keys(redisConfig.connections);
300
- throw new Error(
301
- `[Holo Queue] Queue Redis connection "${connectionName}" was not found in shared Redis config. Available connections: ${availableConnections.join(", ") || "(none)"}.`
302
- );
303
- }
304
- return resolvedConnection;
305
- }
306
- function parseRedisDatabaseFromUrl(url, label) {
307
- if (typeof url === "undefined") {
308
- return void 0;
309
- }
310
- let parsed;
311
- try {
312
- parsed = new URL(url);
313
- } catch (error) {
314
- throw new Error(`[Holo Queue] ${label} is invalid: ${String(error)}`);
315
- }
316
- if (parsed.protocol !== "redis:" && parsed.protocol !== "rediss:") {
317
- throw new Error(`[Holo Queue] ${label} is invalid: unsupported protocol "${parsed.protocol}".`);
318
- }
319
- const pathname = parsed.pathname.replace(/^\/+/, "");
320
- if (!pathname) {
321
- return void 0;
322
- }
323
- const [databaseSegment] = pathname.split("/");
324
- if (!databaseSegment || !/^\d+$/.test(databaseSegment) || pathname !== databaseSegment) {
325
- throw new Error(`[Holo Queue] ${label} must include at most one integer database path segment.`);
326
- }
327
- return Number(databaseSegment);
328
- }
329
- function normalizeRedisClusterNodes(connectionName, nodes) {
330
- if (!nodes || nodes.length === 0) {
331
- return void 0;
332
- }
333
- return Object.freeze(nodes.map((node, index) => {
334
- const label = `queue connection "${connectionName}" redis cluster node ${index + 1}`;
335
- const url = normalizeOptionalRedisString(node.url);
336
- if (typeof url !== "undefined") {
337
- const database = parseRedisDatabaseFromUrl(url, `${label} url`);
338
- if (typeof database !== "undefined") {
339
- throw new Error(`[Holo Queue] ${label} url cannot include a database path in cluster mode.`);
340
- }
341
- }
342
- return Object.freeze({
343
- ...typeof url === "undefined" ? {} : { url },
344
- host: normalizeOptionalRedisString(node.host) ?? DEFAULT_REDIS_HOST,
345
- port: parseInteger(node.port, DEFAULT_REDIS_PORT, `${label} port`, {
346
- minimum: 1
347
- })
348
- });
349
- }));
350
- }
351
- function normalizeRedisOptions(connectionName, base, overrides) {
352
- const hasTargetOverride = typeof overrides?.url !== "undefined" || typeof overrides?.clusters !== "undefined" || typeof overrides?.host !== "undefined" || typeof overrides?.port !== "undefined";
353
- const url = normalizeOptionalRedisString(overrides?.url) ?? (hasTargetOverride ? void 0 : base?.url);
354
- const clusters = typeof overrides?.clusters === "undefined" ? hasTargetOverride ? void 0 : base?.clusters : normalizeRedisClusterNodes(connectionName, overrides.clusters);
355
- const dbFromUrl = parseRedisDatabaseFromUrl(url, `queue connection "${connectionName}" redis url`);
356
- const db = parseInteger(overrides?.db ?? base?.db ?? dbFromUrl, DEFAULT_REDIS_DB, `queue connection "${connectionName}" redis db`, {
357
- minimum: 0
358
- });
359
- if (typeof clusters !== "undefined" && db !== 0) {
360
- throw new Error(`[Holo Queue] queue connection "${connectionName}" cannot select redis.db=${db} in cluster mode; Redis Cluster only supports database 0.`);
361
- }
362
- return Object.freeze({
363
- ...typeof url === "undefined" ? {} : { url },
364
- ...typeof clusters === "undefined" ? {} : { clusters },
365
- host: normalizeOptionalRedisString(overrides?.host) ?? base?.host ?? DEFAULT_REDIS_HOST,
366
- port: parseInteger(overrides?.port ?? base?.port, DEFAULT_REDIS_PORT, `queue connection "${connectionName}" redis port`, {
367
- minimum: 1
368
- }),
369
- password: normalizeOptionalRedisString(overrides?.password) ?? base?.password,
370
- username: normalizeOptionalRedisString(overrides?.username) ?? base?.username,
371
- db
372
- });
373
- }
374
- function normalizeRedisConnection(name, config, redisConfig) {
375
- const explicitConnectionName = config.connection?.trim();
376
- const connectionName = explicitConnectionName || redisConfig?.default;
377
- if (!connectionName && !config.redis) {
378
- throw new Error(
379
- `[Holo Queue] Queue Redis connection "${name}" requires a shared Redis config with a default connection or an explicit connection name.`
380
- );
381
- }
382
- if (!redisConfig && !config.redis) {
383
- throw new Error(
384
- `[Holo Queue] Queue Redis connection "${name}" references shared Redis connection "${connectionName}" but no shared Redis config was provided.`
385
- );
386
- }
387
- const resolvedRedisConnection = redisConfig && connectionName ? resolveSharedRedisConnection(redisConfig, connectionName) : void 0;
388
- return Object.freeze({
389
- name,
390
- driver: "redis",
391
- connection: resolvedRedisConnection?.name ?? connectionName ?? name,
392
- queue: normalizeQueueName(config.queue),
393
- retryAfter: parseInteger(config.retryAfter, DEFAULT_QUEUE_RETRY_AFTER, `queue connection "${name}" retryAfter`, {
394
- minimum: 0
395
- }),
396
- blockFor: parseInteger(config.blockFor, DEFAULT_QUEUE_BLOCK_FOR, `queue connection "${name}" blockFor`, {
397
- minimum: 0
398
- }),
399
- redis: normalizeRedisOptions(name, resolvedRedisConnection, config.redis)
400
- });
401
- }
402
- function normalizeDatabaseConnection(name, config) {
403
- return Object.freeze({
404
- name,
405
- driver: "database",
406
- queue: normalizeQueueName(config.queue),
407
- retryAfter: parseInteger(config.retryAfter, DEFAULT_QUEUE_RETRY_AFTER, `queue connection "${name}" retryAfter`, {
408
- minimum: 0
409
- }),
410
- sleep: parseInteger(config.sleep, DEFAULT_QUEUE_SLEEP, `queue connection "${name}" sleep`, {
411
- minimum: 0
412
- }),
413
- connection: config.connection?.trim() || DEFAULT_FAILED_JOBS_CONNECTION,
414
- table: config.table?.trim() || DEFAULT_DATABASE_QUEUE_TABLE
415
- });
416
- }
417
- function normalizeConnectionConfig(name, config, redisConfig) {
418
- switch (config.driver) {
419
- case "sync":
420
- return normalizeSyncConnection(name, config);
421
- case "redis":
422
- return normalizeRedisConnection(name, config, redisConfig);
423
- case "database":
424
- return normalizeDatabaseConnection(name, config);
425
- default:
426
- throw new Error(`[Holo Queue] Unsupported queue driver "${String(config.driver)}" on connection "${name}".`);
427
- }
428
- }
429
- function normalizeConnections(connections, redisConfig) {
430
- if (!connections || Object.keys(connections).length === 0) {
431
- return DEFAULT_QUEUE_CONFIG.connections;
432
- }
433
- const normalizedEntries = Object.entries(connections).map(([name, config]) => {
434
- const normalizedName = normalizeConnectionName(name, "Queue connection name");
435
- return [normalizedName, normalizeConnectionConfig(normalizedName, config, redisConfig)];
436
- });
437
- return Object.freeze(Object.fromEntries(normalizedEntries));
438
- }
439
- function normalizeFailedStore(config) {
440
- if (config === false) {
441
- return false;
442
- }
443
- const normalized = config ?? DEFAULT_QUEUE_CONFIG.failed;
444
- if (normalized.driver && normalized.driver !== "database") {
445
- throw new Error(`[Holo Queue] Unsupported failed job store driver "${normalized.driver}".`);
446
- }
447
- return Object.freeze({
448
- driver: "database",
449
- connection: normalized.connection?.trim() || DEFAULT_FAILED_JOBS_CONNECTION,
450
- table: normalized.table?.trim() || DEFAULT_FAILED_JOBS_TABLE
451
- });
452
- }
453
- function normalizeQueueConfig(config = {}, redisConfig) {
454
- const connections = normalizeConnections(config.connections, redisConfig);
455
- const connectionNames = Object.keys(connections);
456
- const defaultConnection = config.default?.trim() || connectionNames[0];
457
- if (!connections[defaultConnection]) {
458
- throw new Error(
459
- `[Holo Queue] default queue connection "${defaultConnection}" is not configured. Available connections: ${connectionNames.join(", ")}`
460
- );
461
- }
462
- return Object.freeze({
463
- default: defaultConnection,
464
- failed: normalizeFailedStore(config.failed),
465
- connections
466
- });
467
- }
468
- var holoQueueDefaults = DEFAULT_QUEUE_CONFIG;
469
- var queueInternals = {
470
- parseInteger
471
- };
472
-
473
246
  // src/registry.ts
474
247
  function toPosixPath(value) {
475
248
  return value.replaceAll("\\", "/");
@@ -544,149 +317,6 @@ var queueRegistryInternals = {
544
317
  deriveJobNameFromSourcePath
545
318
  };
546
319
 
547
- // src/drivers/redis.ts
548
- function isModuleNotFoundError(error) {
549
- return !!error && typeof error === "object" && "code" in error && error.code === "ERR_MODULE_NOT_FOUND";
550
- }
551
- async function loadRedisDriverModule() {
552
- try {
553
- const specifier = "@holo-js/queue-redis";
554
- return await import(
555
- /* @vite-ignore */
556
- specifier
557
- );
558
- } catch (error) {
559
- if (isModuleNotFoundError(error)) {
560
- throw new Error("[@holo-js/queue] Redis queue support requires @holo-js/queue-redis to be installed.", {
561
- cause: error
562
- });
563
- }
564
- throw error;
565
- }
566
- }
567
- function normalizeRedisErrorMessage(error) {
568
- if (error instanceof Error) {
569
- return error.message;
570
- }
571
- return String(error);
572
- }
573
- function isRecord(value) {
574
- return typeof value === "object" && value !== null && !Array.isArray(value);
575
- }
576
- function isQueueEnvelope(value) {
577
- return isRecord(value) && typeof value.id === "string" && typeof value.name === "string" && typeof value.connection === "string" && typeof value.queue === "string" && "payload" in value && typeof value.attempts === "number" && Number.isInteger(value.attempts) && value.attempts >= 0 && typeof value.maxAttempts === "number" && Number.isInteger(value.maxAttempts) && value.maxAttempts >= 1 && typeof value.createdAt === "number" && Number.isFinite(value.createdAt) && (typeof value.availableAt === "undefined" || typeof value.availableAt === "number" && Number.isFinite(value.availableAt));
578
- }
579
- function isRedisSocketConnectionTarget(value) {
580
- return value.startsWith("unix://") || value.startsWith("/");
581
- }
582
- function toRedisSocketPath(value) {
583
- return value.startsWith("unix://") ? value.slice("unix://".length) : value;
584
- }
585
- function resolveBullConnectionOptions(connection) {
586
- const redisHost = connection.redis.host;
587
- return {
588
- ...typeof connection.redis.url === "string" ? { url: connection.redis.url } : connection.redis.clusters && connection.redis.clusters.length > 0 ? { clusters: connection.redis.clusters } : typeof redisHost === "string" && isRedisSocketConnectionTarget(redisHost) ? { path: toRedisSocketPath(redisHost) } : {
589
- host: redisHost,
590
- port: connection.redis.port
591
- },
592
- username: connection.redis.username,
593
- password: connection.redis.password,
594
- db: connection.redis.db,
595
- maxRetriesPerRequest: null
596
- };
597
- }
598
- var RedisQueueDriverError = class extends Error {
599
- constructor(connectionName, action, cause) {
600
- super(
601
- `[Holo Queue] Redis queue connection "${connectionName}" failed to ${action}: ${normalizeRedisErrorMessage(cause)}`,
602
- { cause }
603
- );
604
- this.name = "RedisQueueDriverError";
605
- }
606
- };
607
- function wrapRedisError(connectionName, action, error) {
608
- if (error instanceof RedisQueueDriverError) {
609
- return error;
610
- }
611
- return new RedisQueueDriverError(connectionName, action, error);
612
- }
613
- function resolveAttempts(job) {
614
- const attemptsStarted = typeof job.attemptsStarted === "number" && Number.isInteger(job.attemptsStarted) ? job.attemptsStarted : 0;
615
- const attemptsMade = typeof job.attemptsMade === "number" && Number.isInteger(job.attemptsMade) ? job.attemptsMade : 0;
616
- return Math.max(
617
- attemptsStarted > 0 ? attemptsStarted - 1 : 0,
618
- attemptsMade,
619
- 0
620
- );
621
- }
622
- var RedisQueueDriver = class {
623
- constructor(connection, context) {
624
- this.connection = connection;
625
- this.context = context;
626
- this.name = connection.name;
627
- }
628
- name;
629
- driver = "redis";
630
- mode = "async";
631
- driverInstance;
632
- pending;
633
- async resolveDriver() {
634
- if (this.driverInstance) {
635
- return this.driverInstance;
636
- }
637
- this.pending ??= loadRedisDriverModule().then((module) => {
638
- const driver = module.redisQueueDriverFactory.create(this.connection, this.context);
639
- if (driver.mode !== "async") {
640
- throw new Error("[Holo Queue] Redis queue driver must be async.");
641
- }
642
- this.driverInstance = driver;
643
- return driver;
644
- }).finally(() => {
645
- this.pending = void 0;
646
- });
647
- return this.pending;
648
- }
649
- async dispatch(job) {
650
- return (await this.resolveDriver()).dispatch(job);
651
- }
652
- async reserve(input) {
653
- return (await this.resolveDriver()).reserve(input);
654
- }
655
- async acknowledge(job) {
656
- await (await this.resolveDriver()).acknowledge(job);
657
- }
658
- async release(job, options) {
659
- await (await this.resolveDriver()).release(job, options);
660
- }
661
- async delete(job) {
662
- await (await this.resolveDriver()).delete(job);
663
- }
664
- async clear(input) {
665
- return (await this.resolveDriver()).clear(input);
666
- }
667
- async close() {
668
- if (!this.driverInstance && !this.pending) {
669
- return;
670
- }
671
- await (await this.resolveDriver()).close();
672
- }
673
- };
674
- var redisQueueDriverFactory = {
675
- driver: "redis",
676
- create(connection, context) {
677
- return new RedisQueueDriver(connection, context);
678
- }
679
- };
680
- var redisQueueDriverInternals = {
681
- isQueueEnvelope,
682
- loadRedisDriverModule,
683
- normalizeRedisErrorMessage,
684
- resolveAttempts,
685
- resolveBullConnectionOptions,
686
- toRedisSocketPath,
687
- wrapRedisError
688
- };
689
-
690
320
  // src/drivers/sync.ts
691
321
  var SyncQueueDriver = class {
692
322
  name;
@@ -723,6 +353,57 @@ var syncQueueDriverInternals = {
723
353
 
724
354
  // src/runtime.ts
725
355
  import { randomUUID } from "crypto";
356
+
357
+ // src/plugins.ts
358
+ import { resolve } from "path";
359
+ import {
360
+ loadHoloPluginContributionModules,
361
+ loadHoloPluginDefinitions
362
+ } from "@holo-js/kernel";
363
+ var loadedFactoriesByProjectRoot = /* @__PURE__ */ new Map();
364
+ var failedLoadsByProjectRoot = /* @__PURE__ */ new Map();
365
+ function isRecord(value) {
366
+ return !!value && typeof value === "object" && !Array.isArray(value);
367
+ }
368
+ function resolveQueueDriverFactory(moduleValue, packageName, driverName) {
369
+ const candidate = isRecord(moduleValue) && typeof moduleValue.default !== "undefined" ? moduleValue.default : isRecord(moduleValue) && typeof moduleValue.factory !== "undefined" ? moduleValue.factory : moduleValue;
370
+ if (!isRecord(candidate) || candidate.driver !== driverName || typeof candidate.create !== "function") {
371
+ throw new Error(`[@holo-js/queue] Plugin ${packageName} queue driver "${driverName}" must export a matching QueueDriverFactory.`);
372
+ }
373
+ return candidate;
374
+ }
375
+ async function loadQueuePluginDriverFactories(projectRoot = process.cwd(), pluginNames = []) {
376
+ const root = resolve(projectRoot);
377
+ const cacheKey = `${root}\0${[...pluginNames].sort().join("\0")}`;
378
+ const loadedFactories = loadedFactoriesByProjectRoot.get(cacheKey);
379
+ if (loadedFactories) {
380
+ return loadedFactories;
381
+ }
382
+ if (failedLoadsByProjectRoot.has(cacheKey)) {
383
+ throw failedLoadsByProjectRoot.get(cacheKey);
384
+ }
385
+ const plugins = await loadHoloPluginDefinitions(root, pluginNames);
386
+ const contributions = await loadHoloPluginContributionModules(root, plugins, "queue", "drivers");
387
+ let factories;
388
+ try {
389
+ factories = Object.freeze(contributions.map((contribution) => resolveQueueDriverFactory(
390
+ contribution.module,
391
+ contribution.plugin.packageName,
392
+ contribution.name
393
+ )));
394
+ } catch (error) {
395
+ failedLoadsByProjectRoot.set(cacheKey, error);
396
+ throw error;
397
+ }
398
+ loadedFactoriesByProjectRoot.set(cacheKey, factories);
399
+ return factories;
400
+ }
401
+ function resetQueuePluginDriverFactories() {
402
+ loadedFactoriesByProjectRoot.clear();
403
+ failedLoadsByProjectRoot.clear();
404
+ }
405
+
406
+ // src/runtime.ts
726
407
  var INLINE_SYNC_DRIVER_KEY = "__inline_sync__";
727
408
  var QueueReleaseUnsupportedError = class extends Error {
728
409
  constructor() {
@@ -775,14 +456,14 @@ function assertQueueJsonValue(value, path, state) {
775
456
  function validateQueuePayload(payload) {
776
457
  assertQueueJsonValue(payload, "payload", { seen: /* @__PURE__ */ new Set() });
777
458
  }
778
- function normalizeConnectionName2(name) {
459
+ function normalizeConnectionName(name) {
779
460
  const normalized = name.trim();
780
461
  if (!normalized) {
781
462
  throw new Error("[Holo Queue] Queue connection names must be non-empty strings.");
782
463
  }
783
464
  return normalized;
784
465
  }
785
- function normalizeQueueName2(name) {
466
+ function normalizeQueueName(name) {
786
467
  const normalized = name.trim();
787
468
  if (!normalized) {
788
469
  throw new Error("[Holo Queue] Queue names must be non-empty strings.");
@@ -824,7 +505,6 @@ function normalizeDelay(delay) {
824
505
  }
825
506
  function createDefaultDriverFactories() {
826
507
  return /* @__PURE__ */ new Map([
827
- [redisQueueDriverFactory.driver, redisQueueDriverFactory],
828
508
  [syncQueueDriverFactory.driver, syncQueueDriverFactory]
829
509
  ]);
830
510
  }
@@ -868,7 +548,7 @@ function requireRegisteredQueueJob(jobName) {
868
548
  return registered;
869
549
  }
870
550
  function resolveConnectionConfig(config, requestedConnection) {
871
- const connectionName = requestedConnection ? normalizeConnectionName2(requestedConnection) : config.default;
551
+ const connectionName = requestedConnection ? normalizeConnectionName(requestedConnection) : config.default;
872
552
  const connection = config.connections[connectionName];
873
553
  if (!connection) {
874
554
  throw new Error(
@@ -975,6 +655,29 @@ function resolveDriverFactory(state, connection) {
975
655
  }
976
656
  return factory;
977
657
  }
658
+ async function clearCachedDriversForFactoryNames(state, driverNames) {
659
+ const staleDrivers = [];
660
+ for (const [connectionName, driver] of state.drivers.entries()) {
661
+ const connection = state.config.connections[connectionName];
662
+ const driverName = connection?.driver ?? driver.driver;
663
+ if (driverNames.has(driverName)) {
664
+ staleDrivers.push(driver);
665
+ state.drivers.delete(connectionName);
666
+ }
667
+ }
668
+ await closeQueueDrivers(staleDrivers);
669
+ }
670
+ async function loadQueuePluginDrivers(projectRoot = process.cwd(), pluginNames = []) {
671
+ const state = getQueueRuntimeState();
672
+ const loadedDriverNames = /* @__PURE__ */ new Set();
673
+ for (const factory of await loadQueuePluginDriverFactories(projectRoot, pluginNames)) {
674
+ state.driverFactories.set(factory.driver, factory);
675
+ loadedDriverNames.add(factory.driver);
676
+ }
677
+ if (loadedDriverNames.size > 0) {
678
+ await clearCachedDriversForFactoryNames(state, loadedDriverNames);
679
+ }
680
+ }
978
681
  function resolveConnectionDriver(connectionName) {
979
682
  const state = getQueueRuntimeState();
980
683
  const connection = resolveConnectionConfig(state.config, connectionName);
@@ -1010,7 +713,7 @@ function createJobEnvelope(jobName, payload, options) {
1010
713
  runtime.config,
1011
714
  options.connection ?? registered.definition.connection
1012
715
  );
1013
- const queue = normalizeQueueName2(options.queue ?? registered.definition.queue ?? connection.queue ?? DEFAULT_QUEUE_NAME);
716
+ const queue = normalizeQueueName(options.queue ?? registered.definition.queue ?? connection.queue ?? DEFAULT_QUEUE_NAME);
1014
717
  return Object.freeze({
1015
718
  id: randomUUID(),
1016
719
  name: registered.name,
@@ -1054,13 +757,13 @@ var PendingQueueDispatch = class _PendingQueueDispatch {
1054
757
  onConnection(name) {
1055
758
  return new _PendingQueueDispatch(this.jobName, this.payload, {
1056
759
  ...this.options,
1057
- connection: normalizeConnectionName2(name)
760
+ connection: normalizeConnectionName(name)
1058
761
  }, this.completedHooks, this.failedHooks);
1059
762
  }
1060
763
  onQueue(name) {
1061
764
  return new _PendingQueueDispatch(this.jobName, this.payload, {
1062
765
  ...this.options,
1063
- queue: normalizeQueueName2(name)
766
+ queue: normalizeQueueName(name)
1064
767
  }, this.completedHooks, this.failedHooks);
1065
768
  }
1066
769
  delay(value) {
@@ -1130,7 +833,7 @@ var PendingQueueDispatch = class _PendingQueueDispatch {
1130
833
  }
1131
834
  };
1132
835
  function createQueueConnection(name) {
1133
- const resolvedName = name ? normalizeConnectionName2(name) : getQueueRuntimeState().config.default;
836
+ const resolvedName = name ? normalizeConnectionName(name) : getQueueRuntimeState().config.default;
1134
837
  const dispatchViaConnection = ((jobName, payload, options = {}) => {
1135
838
  return new PendingQueueDispatch(jobName, payload, {
1136
839
  ...options,
@@ -1182,6 +885,7 @@ function resetQueueRuntime() {
1182
885
  const state = getQueueRuntimeState();
1183
886
  void closeQueueDrivers(state.drivers.values());
1184
887
  resetQueueRuntimeState(state);
888
+ resetQueuePluginDriverFactories();
1185
889
  }
1186
890
  function getQueueRuntime() {
1187
891
  return createQueueRuntimeBinding(getQueueRuntimeState());
@@ -1232,9 +936,9 @@ var queueRuntimeInternals = {
1232
936
  executeRegisteredQueueJobFailedHook,
1233
937
  getQueueRuntimeState,
1234
938
  isPlainObject,
1235
- normalizeConnectionName: normalizeConnectionName2,
939
+ normalizeConnectionName,
1236
940
  normalizeDelay,
1237
- normalizeQueueName: normalizeQueueName2,
941
+ normalizeQueueName,
1238
942
  resolveConnectionConfig,
1239
943
  resolveConnectionDriver,
1240
944
  resolveDriverFactory,
@@ -1368,7 +1072,7 @@ var QueueWorkerTimeoutError = class extends Error {
1368
1072
  }
1369
1073
  };
1370
1074
  function sleep(milliseconds) {
1371
- return new Promise((resolve) => setTimeout(resolve, milliseconds));
1075
+ return new Promise((resolve2) => setTimeout(resolve2, milliseconds));
1372
1076
  }
1373
1077
  function requireAsyncDriver(driver, connectionName) {
1374
1078
  if (driver.mode !== "async") {
@@ -1759,8 +1463,6 @@ export {
1759
1463
  QueueReleaseUnsupportedError,
1760
1464
  QueueWorkerTimeoutError,
1761
1465
  QueueWorkerUnsupportedDriverError,
1762
- RedisQueueDriver,
1763
- RedisQueueDriverError,
1764
1466
  clearQueueConnection,
1765
1467
  configureQueueRuntime,
1766
1468
  defineJob,
@@ -1775,6 +1477,8 @@ export {
1775
1477
  isQueueJobDefinition,
1776
1478
  listFailedQueueJobs,
1777
1479
  listRegisteredQueueJobs,
1480
+ loadQueuePluginDriverFactories,
1481
+ loadQueuePluginDrivers,
1778
1482
  normalizeQueueConfig,
1779
1483
  normalizeQueueJobDefinition,
1780
1484
  persistFailedQueueJob,
@@ -1784,10 +1488,9 @@ export {
1784
1488
  queueRegistryInternals,
1785
1489
  queueRuntimeInternals,
1786
1490
  queueWorkerInternals,
1787
- redisQueueDriverFactory,
1788
- redisQueueDriverInternals,
1789
1491
  registerQueueJob,
1790
1492
  registerQueueJobs,
1493
+ resetQueuePluginDriverFactories,
1791
1494
  resetQueueRegistry,
1792
1495
  resetQueueRuntime,
1793
1496
  retryFailedQueueJobs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holo-js/queue",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "description": "Holo-JS Framework - queue contracts and config helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -9,6 +9,11 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "import": "./dist/index.mjs",
11
11
  "default": "./dist/index.mjs"
12
+ },
13
+ "./config": {
14
+ "types": "./dist/config.d.ts",
15
+ "import": "./dist/config.mjs",
16
+ "default": "./dist/config.mjs"
12
17
  }
13
18
  },
14
19
  "main": "./dist/index.mjs",
@@ -22,16 +27,11 @@
22
27
  "typecheck": "tsc -p tsconfig.json --noEmit",
23
28
  "test": "vitest --run"
24
29
  },
25
- "peerDependencies": {
26
- "@holo-js/queue-redis": "^0.2.5"
27
- },
28
- "peerDependenciesMeta": {
29
- "@holo-js/queue-redis": {
30
- "optional": true
31
- }
30
+ "dependencies": {
31
+ "@holo-js/config": "^0.3.0",
32
+ "@holo-js/kernel": "^0.3.0"
32
33
  },
33
34
  "devDependencies": {
34
- "@holo-js/queue-redis": "^0.2.5",
35
35
  "@types/node": "^22.10.2",
36
36
  "tsup": "^8.3.5",
37
37
  "typescript": "^5.7.2",