@hogsend/engine 0.25.0 → 0.26.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hogsend/engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
"svix": "^1.95.1",
|
|
41
41
|
"winston": "^3.19.0",
|
|
42
42
|
"zod": "^4.4.3",
|
|
43
|
-
"@hogsend/
|
|
44
|
-
"@hogsend/
|
|
45
|
-
"@hogsend/email": "^0.
|
|
46
|
-
"@hogsend/plugin-posthog": "^0.
|
|
47
|
-
"@hogsend/plugin-resend": "^0.
|
|
43
|
+
"@hogsend/db": "^0.26.0",
|
|
44
|
+
"@hogsend/core": "^0.26.0",
|
|
45
|
+
"@hogsend/email": "^0.26.0",
|
|
46
|
+
"@hogsend/plugin-posthog": "^0.26.0",
|
|
47
|
+
"@hogsend/plugin-resend": "^0.26.0"
|
|
48
48
|
},
|
|
49
49
|
"optionalDependencies": {
|
|
50
|
-
"@hogsend/plugin-postmark": "^0.
|
|
50
|
+
"@hogsend/plugin-postmark": "^0.26.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "^22.15.3",
|
|
@@ -72,6 +72,9 @@ export interface ConnectorRuntimesHandle {
|
|
|
72
72
|
const LEASE_TTL_MS = 30_000;
|
|
73
73
|
const RENEW_MS = 10_000;
|
|
74
74
|
const ELECT_MS = 5_000;
|
|
75
|
+
// ~30s of failed elections (6 * ELECT_MS) before warning loudly that a
|
|
76
|
+
// configured runtime still can't acquire its lease (Redis down or contended).
|
|
77
|
+
const LEASE_MISS_WARN_AT = 6;
|
|
75
78
|
|
|
76
79
|
/** Build the in-process dispatch→transform→ingest sink for one connector. */
|
|
77
80
|
function makeIngest(client: HogsendClient, connector: DefinedConnector) {
|
|
@@ -150,6 +153,7 @@ function startController(
|
|
|
150
153
|
let leading = false;
|
|
151
154
|
let token = "";
|
|
152
155
|
let stopped = false;
|
|
156
|
+
let leaseMisses = 0;
|
|
153
157
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
154
158
|
|
|
155
159
|
/** Drop leadership: heartbeat key deleted FIRST (immediate Offline), then socket. */
|
|
@@ -178,6 +182,7 @@ function startController(
|
|
|
178
182
|
ttlMs: LEASE_TTL_MS,
|
|
179
183
|
});
|
|
180
184
|
if (won) {
|
|
185
|
+
leaseMisses = 0;
|
|
181
186
|
leading = true;
|
|
182
187
|
heartbeat = startConnectorHeartbeat(connectorId, logger);
|
|
183
188
|
heartbeat.state.setMetadata(rt.getMetadata());
|
|
@@ -198,6 +203,22 @@ function startController(
|
|
|
198
203
|
leading = false;
|
|
199
204
|
await releaseLeaderLease({ key: leaseKey, token });
|
|
200
205
|
}
|
|
206
|
+
} else {
|
|
207
|
+
// Lease not acquired: another replica holds it (benign, normal during
|
|
208
|
+
// rollout) OR Redis is unreachable (the gateway can NEVER connect) —
|
|
209
|
+
// indistinguishable from the boolean. Warn LOUDLY once after ~30s of
|
|
210
|
+
// misses so a genuinely stuck runtime surfaces instead of silently
|
|
211
|
+
// never connecting (which Studio otherwise mis-reads as "intents off").
|
|
212
|
+
leaseMisses++;
|
|
213
|
+
if (leaseMisses === LEASE_MISS_WARN_AT) {
|
|
214
|
+
logger.error(
|
|
215
|
+
"Connector runtime has not acquired its leader lease after ~30s — " +
|
|
216
|
+
"Redis unreachable (check REDIS_URL points at the SAME instance " +
|
|
217
|
+
"as the API) or another replica holds it; if none does, the " +
|
|
218
|
+
"gateway will not connect.",
|
|
219
|
+
{ connectorId },
|
|
220
|
+
);
|
|
221
|
+
}
|
|
201
222
|
}
|
|
202
223
|
} else {
|
|
203
224
|
const renewed = await renewLeaderLease({
|
|
@@ -97,7 +97,10 @@ const connectInfoSchema = z.object({
|
|
|
97
97
|
apiPublicUrl: z.string(),
|
|
98
98
|
redirectUri: z.string(),
|
|
99
99
|
interactionsUrl: z.string(),
|
|
100
|
-
|
|
100
|
+
// @deprecated legacy standalone-gateway signal (Boolean(CONNECTOR_INGRESS_SECRET)).
|
|
101
|
+
// The default inline runtime never uses the ingress secret; readiness is
|
|
102
|
+
// `workerOnline` (the owned Redis heartbeat). Kept one minor; NOT a precondition.
|
|
103
|
+
legacyIngressSecretConfigured: z.boolean(),
|
|
101
104
|
credentialStored: z.boolean(),
|
|
102
105
|
guildId: z.string().nullable(),
|
|
103
106
|
// Tri-state — null = unknown (no guild from worker or derived credential).
|
|
@@ -420,7 +423,7 @@ export const adminConnectorsRouter = new OpenAPIHono<AppEnv>()
|
|
|
420
423
|
apiPublicUrl,
|
|
421
424
|
redirectUri,
|
|
422
425
|
interactionsUrl: `${apiPublicUrl}/v1/connectors/discord/interactions`,
|
|
423
|
-
|
|
426
|
+
legacyIngressSecretConfigured: Boolean(env.CONNECTOR_INGRESS_SECRET),
|
|
424
427
|
credentialStored: derived !== null,
|
|
425
428
|
guildId,
|
|
426
429
|
// Tri-state — a guild id (live or derived) confirms install; else null.
|