@cjhyy/code-shell-chat 0.9.9 → 0.9.10

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.
@@ -49,6 +49,8 @@ export declare class DeliveryQueue {
49
49
  private readonly pending;
50
50
  /** Enqueues that reserved capacity while attachments are materialized outside the mutation lock. */
51
51
  private readonly preparing;
52
+ /** Same-target inputs enter the queue in arrival order, even when media loads slowly. */
53
+ private readonly preparationByTarget;
52
54
  private readonly completed;
53
55
  private readonly inFlight;
54
56
  private readonly targetInFlight;
@@ -36,6 +36,8 @@ export class DeliveryQueue {
36
36
  pending = [];
37
37
  /** Enqueues that reserved capacity while attachments are materialized outside the mutation lock. */
38
38
  preparing = new Map();
39
+ /** Same-target inputs enter the queue in arrival order, even when media loads slowly. */
40
+ preparationByTarget = new Map();
39
41
  completed = new Map();
40
42
  inFlight = new Set();
41
43
  targetInFlight = new Map();
@@ -81,6 +83,10 @@ export class DeliveryQueue {
81
83
  throw new Error("Chat Gateway inbox is stopped");
82
84
  const dedupeKey = deliveryDedupeKey(message);
83
85
  const id = randomUUID();
86
+ const target = targetKey(message);
87
+ let previousPreparation;
88
+ let preparation;
89
+ let releasePreparation;
84
90
  const reserved = await this.withMutation(async () => {
85
91
  if (this.stopped)
86
92
  throw new Error("Chat Gateway inbox is stopped");
@@ -95,6 +101,11 @@ export class DeliveryQueue {
95
101
  throw new DeliveryBackpressureError(this.config.maxPending);
96
102
  }
97
103
  this.preparing.set(id, dedupeKey);
104
+ previousPreparation = this.preparationByTarget.get(target);
105
+ preparation = new Promise((resolve) => {
106
+ releasePreparation = resolve;
107
+ });
108
+ this.preparationByTarget.set(target, preparation);
98
109
  return true;
99
110
  });
100
111
  if (!reserved)
@@ -103,6 +114,7 @@ export class DeliveryQueue {
103
114
  // above preserves dedupe/backpressure, while doing the I/O here prevents one
104
115
  // slow attachment from blocking every enqueue and terminal state write.
105
116
  const spooled = await this.spoolAttachments(id, message);
117
+ await previousPreparation;
106
118
  let record;
107
119
  try {
108
120
  await this.withMutation(async () => {
@@ -152,6 +164,12 @@ export class DeliveryQueue {
152
164
  });
153
165
  throw error;
154
166
  }
167
+ finally {
168
+ releasePreparation?.();
169
+ if (this.preparationByTarget.get(target) === preparation) {
170
+ this.preparationByTarget.delete(target);
171
+ }
172
+ }
155
173
  this.pump();
156
174
  return "queued";
157
175
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cjhyy/code-shell-chat",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
4
4
  "description": "A standalone, transport-agnostic multi-channel chat gateway for Node.js and Bun.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",