@volter/supercode-teams 0.3.122 → 0.3.123

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 (2) hide show
  1. package/package.json +1 -1
  2. package/worker/index.mjs +33 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-teams",
3
- "version": "0.3.122",
3
+ "version": "0.3.123",
4
4
  "type": "module",
5
5
  "description": "A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.",
6
6
  "license": "MIT",
package/worker/index.mjs CHANGED
@@ -143,15 +143,42 @@ export class TeamsServer extends DurableObject {
143
143
  }
144
144
  }
145
145
 
146
+ /** What the Durable Object's runtime said of a failed call (its error's own flags), for the log and the answer. */
147
+ const objectFailure = (error) => ({
148
+ name: String(error?.name ?? 'Error'),
149
+ message: String(error?.message ?? error).slice(0, 200),
150
+ retryable: error?.retryable === true,
151
+ overloaded: error?.overloaded === true,
152
+ remote: error?.remote === true,
153
+ reset: error?.durableObjectReset === true,
154
+ });
155
+
146
156
  export default {
147
157
  async fetch(request, env) {
148
- try { return await env.TEAMS_SERVER.get(env.TEAMS_SERVER.idFromName('server')).fetch(request); }
158
+ const repeatable = request.method === 'GET' || request.method === 'HEAD';
159
+ const call = () => env.TEAMS_SERVER.get(env.TEAMS_SERVER.idFromName('server')).fetch(repeatable ? request.clone() : request);
160
+ // A request safe to repeat (a read, or a link's WebSocket upgrade: every machine's connection) is tried once more
161
+ // when the runtime says the failure is retryable and the object is not overloaded: a reset object (its code
162
+ // updated, or evicted and restarted) answers the second call. Fleet-wide 503s for minutes with no deploy behind
163
+ // them (2026-10-06, 14:04Z and 18:41-18:44Z) dropped every machine's link; what the runtime said of them was only
164
+ // in the log, which now says it in one JSON line and the answer names it.
165
+ let first = null;
166
+ try { return await call(); }
149
167
  catch (error) {
150
- // Failures before the HTTP handler (object initialization, migrations or
151
- // storage) otherwise become a platform HTML page, not our API contract.
152
- const requestId = crypto.randomUUID();
153
- console.error(`Teams request ${requestId} failed before response: ${error.message}`);
154
- return Response.json({ version: 1, error: { code: 'unavailable', message: 'Teams server is temporarily unavailable', request_id: requestId, retryable: true } }, { status: 503, headers: { 'Retry-After': '5', 'X-Request-ID': requestId } });
168
+ first = objectFailure(error);
169
+ if (!(repeatable && first.retryable && !first.overloaded)) return unavailable(first, null);
155
170
  }
171
+ try { return await call(); }
172
+ catch (error) { return unavailable(objectFailure(error), first); }
156
173
  },
157
174
  };
175
+
176
+ /** Failures before the HTTP handler (object initialization, migrations, storage, a reset) as our API contract, not a
177
+ * platform HTML page. The answer goes to callers not yet authenticated, so it names only the error's kind and the
178
+ * runtime's flags; its message (storage or SQL text, internal paths) is in the log line its request id leads to. */
179
+ function unavailable(failure, retried) {
180
+ const requestId = crypto.randomUUID();
181
+ console.error(JSON.stringify({ event: 'teams_unavailable', request_id: requestId, failure, ...(retried ? { first: retried } : {}) }));
182
+ const cause = `${failure.name}${failure.reset ? ', object reset' : ''}${failure.overloaded ? ', overloaded' : ''}${retried ? ', after one retry' : ''}`;
183
+ return Response.json({ version: 1, error: { code: 'unavailable', message: `Teams server is temporarily unavailable (${cause})`, request_id: requestId, retryable: true, cause: { name: failure.name, retryable: failure.retryable, overloaded: failure.overloaded, remote: failure.remote, reset: failure.reset } } }, { status: 503, headers: { 'Retry-After': failure.overloaded ? '15' : '5', 'X-Request-ID': requestId } });
184
+ }