@absolutejs/voice 0.0.22-beta.387 → 0.0.22-beta.388
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/client/index.js +66 -51
- package/dist/index.js +68 -53
- package/dist/proofTrends.d.ts +2 -0
- package/dist/react/index.js +66 -51
- package/dist/vue/index.js +66 -51
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -6557,6 +6557,7 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
6557
6557
|
const requestTimeoutMs = options.requestTimeoutMs ?? 5000;
|
|
6558
6558
|
const jobPollMs = options.jobPollMs ?? 1200;
|
|
6559
6559
|
const jobTimeoutMs = options.jobTimeoutMs ?? 600000;
|
|
6560
|
+
const maxPasses = typeof options.maxPasses === "number" && Number.isFinite(options.maxPasses) && options.maxPasses > 0 ? Math.floor(options.maxPasses) : 3;
|
|
6560
6561
|
const readinessCheckLabel = options.readinessCheckLabel ?? "Real-call profile history";
|
|
6561
6562
|
const fetchImpl = options.fetch ?? fetch;
|
|
6562
6563
|
const recoveryActionsHref = options.recoveryActionsHref ?? "/api/production-readiness/recovery-actions";
|
|
@@ -6598,70 +6599,84 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
6598
6599
|
actionCount: 0,
|
|
6599
6600
|
actions,
|
|
6600
6601
|
jobs: [],
|
|
6602
|
+
passes: 0,
|
|
6601
6603
|
ok: realCallProfileGate2?.status === "pass",
|
|
6602
6604
|
realCallProfileGate: realCallProfileGate2,
|
|
6603
6605
|
startFailures: []
|
|
6604
6606
|
};
|
|
6605
6607
|
}
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
6627
|
-
}
|
|
6628
|
-
] : []);
|
|
6629
|
-
const pollJob = async (jobId) => {
|
|
6630
|
-
const deadline = Date.now() + jobTimeoutMs;
|
|
6631
|
-
while (Date.now() < deadline) {
|
|
6632
|
-
const body = await fetchJson(resolveJobHref(jobId));
|
|
6633
|
-
const job = body.job;
|
|
6634
|
-
if (!job) {
|
|
6635
|
-
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
6608
|
+
const allJobs = [];
|
|
6609
|
+
const allStartFailures = [];
|
|
6610
|
+
let realCallProfileGate = null;
|
|
6611
|
+
let passes = 0;
|
|
6612
|
+
for (let pass = 1;pass <= maxPasses; pass += 1) {
|
|
6613
|
+
passes = pass;
|
|
6614
|
+
options.logger?.log(`Running ${String(actions.length)} real-call profile recovery action(s) in parallel (pass ${String(pass)}/${String(maxPasses)}).`);
|
|
6615
|
+
for (const action of actions) {
|
|
6616
|
+
options.logger?.log(`- ${describeVoiceRealCallProfileRecoveryLoopAction(action)}`);
|
|
6617
|
+
}
|
|
6618
|
+
const starts = await Promise.allSettled(actions.map(async (action) => {
|
|
6619
|
+
if (!action.href) {
|
|
6620
|
+
throw new Error("Recovery action is missing href.");
|
|
6621
|
+
}
|
|
6622
|
+
const body = await fetchJson(action.href, { method: "POST" });
|
|
6623
|
+
return { action, ...body };
|
|
6624
|
+
}));
|
|
6625
|
+
const startedJobs = starts.flatMap((result) => {
|
|
6626
|
+
if (result.status === "rejected") {
|
|
6627
|
+
return [];
|
|
6636
6628
|
}
|
|
6637
|
-
|
|
6638
|
-
|
|
6629
|
+
return result.value.jobId ? [result.value] : [];
|
|
6630
|
+
});
|
|
6631
|
+
const startFailures = starts.flatMap((result, index) => result.status === "rejected" ? [
|
|
6632
|
+
{
|
|
6633
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(actions[index] ?? {}),
|
|
6634
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
6639
6635
|
}
|
|
6640
|
-
|
|
6636
|
+
] : []);
|
|
6637
|
+
allStartFailures.push(...startFailures);
|
|
6638
|
+
const pollJob = async (jobId) => {
|
|
6639
|
+
const deadline = Date.now() + jobTimeoutMs;
|
|
6640
|
+
while (Date.now() < deadline) {
|
|
6641
|
+
const body = await fetchJson(resolveJobHref(jobId));
|
|
6642
|
+
const job = body.job;
|
|
6643
|
+
if (!job) {
|
|
6644
|
+
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
6645
|
+
}
|
|
6646
|
+
if (job.status === "pass" || job.status === "fail") {
|
|
6647
|
+
return job;
|
|
6648
|
+
}
|
|
6649
|
+
await sleepVoiceRealCallProfileRecoveryLoop(jobPollMs);
|
|
6650
|
+
}
|
|
6651
|
+
throw new Error(`Timed out waiting ${String(jobTimeoutMs)}ms for recovery job ${jobId}.`);
|
|
6652
|
+
};
|
|
6653
|
+
options.logger?.log(`Polling ${String(startedJobs.length)} recovery job(s) in parallel.`);
|
|
6654
|
+
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
6655
|
+
const jobs = jobResults.map((result, index) => ({
|
|
6656
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
6657
|
+
jobId: startedJobs[index]?.jobId,
|
|
6658
|
+
result: result.status === "fulfilled" ? result.value : {
|
|
6659
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
6660
|
+
status: "fail"
|
|
6661
|
+
}
|
|
6662
|
+
}));
|
|
6663
|
+
allJobs.push(...jobs);
|
|
6664
|
+
if (refreshHref !== false) {
|
|
6665
|
+
await fetchJson(refreshHref, { method: "POST" });
|
|
6641
6666
|
}
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
6646
|
-
const jobs = jobResults.map((result, index) => ({
|
|
6647
|
-
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
6648
|
-
jobId: startedJobs[index]?.jobId,
|
|
6649
|
-
result: result.status === "fulfilled" ? result.value : {
|
|
6650
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
6651
|
-
status: "fail"
|
|
6667
|
+
realCallProfileGate = await getGate(true);
|
|
6668
|
+
if (realCallProfileGate?.status === "pass") {
|
|
6669
|
+
break;
|
|
6652
6670
|
}
|
|
6653
|
-
}));
|
|
6654
|
-
if (refreshHref !== false) {
|
|
6655
|
-
await fetchJson(refreshHref, { method: "POST" });
|
|
6656
6671
|
}
|
|
6657
|
-
const realCallProfileGate = await getGate(true);
|
|
6658
6672
|
return {
|
|
6659
|
-
actionCount: actions.length,
|
|
6673
|
+
actionCount: actions.length * passes,
|
|
6660
6674
|
actions,
|
|
6661
|
-
jobs,
|
|
6662
|
-
|
|
6675
|
+
jobs: allJobs,
|
|
6676
|
+
passes,
|
|
6677
|
+
ok: allStartFailures.length === 0 && allJobs.every((job) => job.result.status === "pass") && realCallProfileGate?.status === "pass",
|
|
6663
6678
|
realCallProfileGate,
|
|
6664
|
-
startFailures
|
|
6679
|
+
startFailures: allStartFailures
|
|
6665
6680
|
};
|
|
6666
6681
|
};
|
|
6667
6682
|
var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
|
package/dist/index.js
CHANGED
|
@@ -17076,6 +17076,7 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
17076
17076
|
const requestTimeoutMs = options.requestTimeoutMs ?? 5000;
|
|
17077
17077
|
const jobPollMs = options.jobPollMs ?? 1200;
|
|
17078
17078
|
const jobTimeoutMs = options.jobTimeoutMs ?? 600000;
|
|
17079
|
+
const maxPasses = typeof options.maxPasses === "number" && Number.isFinite(options.maxPasses) && options.maxPasses > 0 ? Math.floor(options.maxPasses) : 3;
|
|
17079
17080
|
const readinessCheckLabel = options.readinessCheckLabel ?? "Real-call profile history";
|
|
17080
17081
|
const fetchImpl = options.fetch ?? fetch;
|
|
17081
17082
|
const recoveryActionsHref = options.recoveryActionsHref ?? "/api/production-readiness/recovery-actions";
|
|
@@ -17117,70 +17118,84 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
17117
17118
|
actionCount: 0,
|
|
17118
17119
|
actions,
|
|
17119
17120
|
jobs: [],
|
|
17121
|
+
passes: 0,
|
|
17120
17122
|
ok: realCallProfileGate2?.status === "pass",
|
|
17121
17123
|
realCallProfileGate: realCallProfileGate2,
|
|
17122
17124
|
startFailures: []
|
|
17123
17125
|
};
|
|
17124
17126
|
}
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17138
|
-
|
|
17127
|
+
const allJobs = [];
|
|
17128
|
+
const allStartFailures = [];
|
|
17129
|
+
let realCallProfileGate = null;
|
|
17130
|
+
let passes = 0;
|
|
17131
|
+
for (let pass = 1;pass <= maxPasses; pass += 1) {
|
|
17132
|
+
passes = pass;
|
|
17133
|
+
options.logger?.log(`Running ${String(actions.length)} real-call profile recovery action(s) in parallel (pass ${String(pass)}/${String(maxPasses)}).`);
|
|
17134
|
+
for (const action of actions) {
|
|
17135
|
+
options.logger?.log(`- ${describeVoiceRealCallProfileRecoveryLoopAction(action)}`);
|
|
17136
|
+
}
|
|
17137
|
+
const starts = await Promise.allSettled(actions.map(async (action) => {
|
|
17138
|
+
if (!action.href) {
|
|
17139
|
+
throw new Error("Recovery action is missing href.");
|
|
17140
|
+
}
|
|
17141
|
+
const body = await fetchJson(action.href, { method: "POST" });
|
|
17142
|
+
return { action, ...body };
|
|
17143
|
+
}));
|
|
17144
|
+
const startedJobs = starts.flatMap((result) => {
|
|
17145
|
+
if (result.status === "rejected") {
|
|
17146
|
+
return [];
|
|
17147
|
+
}
|
|
17148
|
+
return result.value.jobId ? [result.value] : [];
|
|
17149
|
+
});
|
|
17150
|
+
const startFailures = starts.flatMap((result, index) => result.status === "rejected" ? [
|
|
17151
|
+
{
|
|
17152
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(actions[index] ?? {}),
|
|
17153
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
17154
|
+
}
|
|
17155
|
+
] : []);
|
|
17156
|
+
allStartFailures.push(...startFailures);
|
|
17157
|
+
const pollJob = async (jobId) => {
|
|
17158
|
+
const deadline = Date.now() + jobTimeoutMs;
|
|
17159
|
+
while (Date.now() < deadline) {
|
|
17160
|
+
const body = await fetchJson(resolveJobHref(jobId));
|
|
17161
|
+
const job = body.job;
|
|
17162
|
+
if (!job) {
|
|
17163
|
+
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
17164
|
+
}
|
|
17165
|
+
if (job.status === "pass" || job.status === "fail") {
|
|
17166
|
+
return job;
|
|
17167
|
+
}
|
|
17168
|
+
await sleepVoiceRealCallProfileRecoveryLoop(jobPollMs);
|
|
17169
|
+
}
|
|
17170
|
+
throw new Error(`Timed out waiting ${String(jobTimeoutMs)}ms for recovery job ${jobId}.`);
|
|
17171
|
+
};
|
|
17172
|
+
options.logger?.log(`Polling ${String(startedJobs.length)} recovery job(s) in parallel.`);
|
|
17173
|
+
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
17174
|
+
const jobs = jobResults.map((result, index) => ({
|
|
17175
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
17176
|
+
jobId: startedJobs[index]?.jobId,
|
|
17177
|
+
result: result.status === "fulfilled" ? result.value : {
|
|
17178
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
17179
|
+
status: "fail"
|
|
17180
|
+
}
|
|
17181
|
+
}));
|
|
17182
|
+
allJobs.push(...jobs);
|
|
17183
|
+
if (refreshHref !== false) {
|
|
17184
|
+
await fetchJson(refreshHref, { method: "POST" });
|
|
17139
17185
|
}
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
{
|
|
17144
|
-
action: describeVoiceRealCallProfileRecoveryLoopAction(actions[index] ?? {}),
|
|
17145
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
17146
|
-
}
|
|
17147
|
-
] : []);
|
|
17148
|
-
const pollJob = async (jobId) => {
|
|
17149
|
-
const deadline = Date.now() + jobTimeoutMs;
|
|
17150
|
-
while (Date.now() < deadline) {
|
|
17151
|
-
const body = await fetchJson(resolveJobHref(jobId));
|
|
17152
|
-
const job = body.job;
|
|
17153
|
-
if (!job) {
|
|
17154
|
-
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
17155
|
-
}
|
|
17156
|
-
if (job.status === "pass" || job.status === "fail") {
|
|
17157
|
-
return job;
|
|
17158
|
-
}
|
|
17159
|
-
await sleepVoiceRealCallProfileRecoveryLoop(jobPollMs);
|
|
17160
|
-
}
|
|
17161
|
-
throw new Error(`Timed out waiting ${String(jobTimeoutMs)}ms for recovery job ${jobId}.`);
|
|
17162
|
-
};
|
|
17163
|
-
options.logger?.log(`Polling ${String(startedJobs.length)} recovery job(s) in parallel.`);
|
|
17164
|
-
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
17165
|
-
const jobs = jobResults.map((result, index) => ({
|
|
17166
|
-
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
17167
|
-
jobId: startedJobs[index]?.jobId,
|
|
17168
|
-
result: result.status === "fulfilled" ? result.value : {
|
|
17169
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
17170
|
-
status: "fail"
|
|
17186
|
+
realCallProfileGate = await getGate(true);
|
|
17187
|
+
if (realCallProfileGate?.status === "pass") {
|
|
17188
|
+
break;
|
|
17171
17189
|
}
|
|
17172
|
-
}));
|
|
17173
|
-
if (refreshHref !== false) {
|
|
17174
|
-
await fetchJson(refreshHref, { method: "POST" });
|
|
17175
17190
|
}
|
|
17176
|
-
const realCallProfileGate = await getGate(true);
|
|
17177
17191
|
return {
|
|
17178
|
-
actionCount: actions.length,
|
|
17192
|
+
actionCount: actions.length * passes,
|
|
17179
17193
|
actions,
|
|
17180
|
-
jobs,
|
|
17181
|
-
|
|
17194
|
+
jobs: allJobs,
|
|
17195
|
+
passes,
|
|
17196
|
+
ok: allStartFailures.length === 0 && allJobs.every((job) => job.result.status === "pass") && realCallProfileGate?.status === "pass",
|
|
17182
17197
|
realCallProfileGate,
|
|
17183
|
-
startFailures
|
|
17198
|
+
startFailures: allStartFailures
|
|
17184
17199
|
};
|
|
17185
17200
|
};
|
|
17186
17201
|
var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
|
package/dist/proofTrends.d.ts
CHANGED
|
@@ -492,6 +492,7 @@ export type VoiceRealCallProfileRecoveryLoopReport = {
|
|
|
492
492
|
actionCount: number;
|
|
493
493
|
actions: VoiceRealCallProfileRecoveryLoopAction[];
|
|
494
494
|
jobs: VoiceRealCallProfileRecoveryLoopJobResult[];
|
|
495
|
+
passes: number;
|
|
495
496
|
ok: boolean;
|
|
496
497
|
realCallProfileGate: VoiceProductionReadinessCheck | null;
|
|
497
498
|
startFailures: VoiceRealCallProfileRecoveryLoopStartFailure[];
|
|
@@ -504,6 +505,7 @@ export type VoiceRealCallProfileRecoveryLoopOptions = {
|
|
|
504
505
|
jobPollMs?: number;
|
|
505
506
|
jobTimeoutMs?: number;
|
|
506
507
|
logger?: Pick<Console, 'log'>;
|
|
508
|
+
maxPasses?: number;
|
|
507
509
|
readinessCheckLabel?: string;
|
|
508
510
|
readinessHref?: string;
|
|
509
511
|
recoveryActionsHref?: string;
|
package/dist/react/index.js
CHANGED
|
@@ -4144,6 +4144,7 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
4144
4144
|
const requestTimeoutMs = options.requestTimeoutMs ?? 5000;
|
|
4145
4145
|
const jobPollMs = options.jobPollMs ?? 1200;
|
|
4146
4146
|
const jobTimeoutMs = options.jobTimeoutMs ?? 600000;
|
|
4147
|
+
const maxPasses = typeof options.maxPasses === "number" && Number.isFinite(options.maxPasses) && options.maxPasses > 0 ? Math.floor(options.maxPasses) : 3;
|
|
4147
4148
|
const readinessCheckLabel = options.readinessCheckLabel ?? "Real-call profile history";
|
|
4148
4149
|
const fetchImpl = options.fetch ?? fetch;
|
|
4149
4150
|
const recoveryActionsHref = options.recoveryActionsHref ?? "/api/production-readiness/recovery-actions";
|
|
@@ -4185,70 +4186,84 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
4185
4186
|
actionCount: 0,
|
|
4186
4187
|
actions,
|
|
4187
4188
|
jobs: [],
|
|
4189
|
+
passes: 0,
|
|
4188
4190
|
ok: realCallProfileGate2?.status === "pass",
|
|
4189
4191
|
realCallProfileGate: realCallProfileGate2,
|
|
4190
4192
|
startFailures: []
|
|
4191
4193
|
};
|
|
4192
4194
|
}
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
4214
|
-
}
|
|
4215
|
-
] : []);
|
|
4216
|
-
const pollJob = async (jobId) => {
|
|
4217
|
-
const deadline = Date.now() + jobTimeoutMs;
|
|
4218
|
-
while (Date.now() < deadline) {
|
|
4219
|
-
const body = await fetchJson(resolveJobHref(jobId));
|
|
4220
|
-
const job = body.job;
|
|
4221
|
-
if (!job) {
|
|
4222
|
-
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
4195
|
+
const allJobs = [];
|
|
4196
|
+
const allStartFailures = [];
|
|
4197
|
+
let realCallProfileGate = null;
|
|
4198
|
+
let passes = 0;
|
|
4199
|
+
for (let pass = 1;pass <= maxPasses; pass += 1) {
|
|
4200
|
+
passes = pass;
|
|
4201
|
+
options.logger?.log(`Running ${String(actions.length)} real-call profile recovery action(s) in parallel (pass ${String(pass)}/${String(maxPasses)}).`);
|
|
4202
|
+
for (const action of actions) {
|
|
4203
|
+
options.logger?.log(`- ${describeVoiceRealCallProfileRecoveryLoopAction(action)}`);
|
|
4204
|
+
}
|
|
4205
|
+
const starts = await Promise.allSettled(actions.map(async (action) => {
|
|
4206
|
+
if (!action.href) {
|
|
4207
|
+
throw new Error("Recovery action is missing href.");
|
|
4208
|
+
}
|
|
4209
|
+
const body = await fetchJson(action.href, { method: "POST" });
|
|
4210
|
+
return { action, ...body };
|
|
4211
|
+
}));
|
|
4212
|
+
const startedJobs = starts.flatMap((result) => {
|
|
4213
|
+
if (result.status === "rejected") {
|
|
4214
|
+
return [];
|
|
4223
4215
|
}
|
|
4224
|
-
|
|
4225
|
-
|
|
4216
|
+
return result.value.jobId ? [result.value] : [];
|
|
4217
|
+
});
|
|
4218
|
+
const startFailures = starts.flatMap((result, index) => result.status === "rejected" ? [
|
|
4219
|
+
{
|
|
4220
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(actions[index] ?? {}),
|
|
4221
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
4226
4222
|
}
|
|
4227
|
-
|
|
4223
|
+
] : []);
|
|
4224
|
+
allStartFailures.push(...startFailures);
|
|
4225
|
+
const pollJob = async (jobId) => {
|
|
4226
|
+
const deadline = Date.now() + jobTimeoutMs;
|
|
4227
|
+
while (Date.now() < deadline) {
|
|
4228
|
+
const body = await fetchJson(resolveJobHref(jobId));
|
|
4229
|
+
const job = body.job;
|
|
4230
|
+
if (!job) {
|
|
4231
|
+
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
4232
|
+
}
|
|
4233
|
+
if (job.status === "pass" || job.status === "fail") {
|
|
4234
|
+
return job;
|
|
4235
|
+
}
|
|
4236
|
+
await sleepVoiceRealCallProfileRecoveryLoop(jobPollMs);
|
|
4237
|
+
}
|
|
4238
|
+
throw new Error(`Timed out waiting ${String(jobTimeoutMs)}ms for recovery job ${jobId}.`);
|
|
4239
|
+
};
|
|
4240
|
+
options.logger?.log(`Polling ${String(startedJobs.length)} recovery job(s) in parallel.`);
|
|
4241
|
+
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
4242
|
+
const jobs = jobResults.map((result, index) => ({
|
|
4243
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
4244
|
+
jobId: startedJobs[index]?.jobId,
|
|
4245
|
+
result: result.status === "fulfilled" ? result.value : {
|
|
4246
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
4247
|
+
status: "fail"
|
|
4248
|
+
}
|
|
4249
|
+
}));
|
|
4250
|
+
allJobs.push(...jobs);
|
|
4251
|
+
if (refreshHref !== false) {
|
|
4252
|
+
await fetchJson(refreshHref, { method: "POST" });
|
|
4228
4253
|
}
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
4233
|
-
const jobs = jobResults.map((result, index) => ({
|
|
4234
|
-
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
4235
|
-
jobId: startedJobs[index]?.jobId,
|
|
4236
|
-
result: result.status === "fulfilled" ? result.value : {
|
|
4237
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
4238
|
-
status: "fail"
|
|
4254
|
+
realCallProfileGate = await getGate(true);
|
|
4255
|
+
if (realCallProfileGate?.status === "pass") {
|
|
4256
|
+
break;
|
|
4239
4257
|
}
|
|
4240
|
-
}));
|
|
4241
|
-
if (refreshHref !== false) {
|
|
4242
|
-
await fetchJson(refreshHref, { method: "POST" });
|
|
4243
4258
|
}
|
|
4244
|
-
const realCallProfileGate = await getGate(true);
|
|
4245
4259
|
return {
|
|
4246
|
-
actionCount: actions.length,
|
|
4260
|
+
actionCount: actions.length * passes,
|
|
4247
4261
|
actions,
|
|
4248
|
-
jobs,
|
|
4249
|
-
|
|
4262
|
+
jobs: allJobs,
|
|
4263
|
+
passes,
|
|
4264
|
+
ok: allStartFailures.length === 0 && allJobs.every((job) => job.result.status === "pass") && realCallProfileGate?.status === "pass",
|
|
4250
4265
|
realCallProfileGate,
|
|
4251
|
-
startFailures
|
|
4266
|
+
startFailures: allStartFailures
|
|
4252
4267
|
};
|
|
4253
4268
|
};
|
|
4254
4269
|
var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
|
package/dist/vue/index.js
CHANGED
|
@@ -4065,6 +4065,7 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
4065
4065
|
const requestTimeoutMs = options.requestTimeoutMs ?? 5000;
|
|
4066
4066
|
const jobPollMs = options.jobPollMs ?? 1200;
|
|
4067
4067
|
const jobTimeoutMs = options.jobTimeoutMs ?? 600000;
|
|
4068
|
+
const maxPasses = typeof options.maxPasses === "number" && Number.isFinite(options.maxPasses) && options.maxPasses > 0 ? Math.floor(options.maxPasses) : 3;
|
|
4068
4069
|
const readinessCheckLabel = options.readinessCheckLabel ?? "Real-call profile history";
|
|
4069
4070
|
const fetchImpl = options.fetch ?? fetch;
|
|
4070
4071
|
const recoveryActionsHref = options.recoveryActionsHref ?? "/api/production-readiness/recovery-actions";
|
|
@@ -4106,70 +4107,84 @@ var runVoiceRealCallProfileRecoveryLoop = async (options) => {
|
|
|
4106
4107
|
actionCount: 0,
|
|
4107
4108
|
actions,
|
|
4108
4109
|
jobs: [],
|
|
4110
|
+
passes: 0,
|
|
4109
4111
|
ok: realCallProfileGate2?.status === "pass",
|
|
4110
4112
|
realCallProfileGate: realCallProfileGate2,
|
|
4111
4113
|
startFailures: []
|
|
4112
4114
|
};
|
|
4113
4115
|
}
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
4135
|
-
}
|
|
4136
|
-
] : []);
|
|
4137
|
-
const pollJob = async (jobId) => {
|
|
4138
|
-
const deadline = Date.now() + jobTimeoutMs;
|
|
4139
|
-
while (Date.now() < deadline) {
|
|
4140
|
-
const body = await fetchJson(resolveJobHref(jobId));
|
|
4141
|
-
const job = body.job;
|
|
4142
|
-
if (!job) {
|
|
4143
|
-
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
4116
|
+
const allJobs = [];
|
|
4117
|
+
const allStartFailures = [];
|
|
4118
|
+
let realCallProfileGate = null;
|
|
4119
|
+
let passes = 0;
|
|
4120
|
+
for (let pass = 1;pass <= maxPasses; pass += 1) {
|
|
4121
|
+
passes = pass;
|
|
4122
|
+
options.logger?.log(`Running ${String(actions.length)} real-call profile recovery action(s) in parallel (pass ${String(pass)}/${String(maxPasses)}).`);
|
|
4123
|
+
for (const action of actions) {
|
|
4124
|
+
options.logger?.log(`- ${describeVoiceRealCallProfileRecoveryLoopAction(action)}`);
|
|
4125
|
+
}
|
|
4126
|
+
const starts = await Promise.allSettled(actions.map(async (action) => {
|
|
4127
|
+
if (!action.href) {
|
|
4128
|
+
throw new Error("Recovery action is missing href.");
|
|
4129
|
+
}
|
|
4130
|
+
const body = await fetchJson(action.href, { method: "POST" });
|
|
4131
|
+
return { action, ...body };
|
|
4132
|
+
}));
|
|
4133
|
+
const startedJobs = starts.flatMap((result) => {
|
|
4134
|
+
if (result.status === "rejected") {
|
|
4135
|
+
return [];
|
|
4144
4136
|
}
|
|
4145
|
-
|
|
4146
|
-
|
|
4137
|
+
return result.value.jobId ? [result.value] : [];
|
|
4138
|
+
});
|
|
4139
|
+
const startFailures = starts.flatMap((result, index) => result.status === "rejected" ? [
|
|
4140
|
+
{
|
|
4141
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(actions[index] ?? {}),
|
|
4142
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
4147
4143
|
}
|
|
4148
|
-
|
|
4144
|
+
] : []);
|
|
4145
|
+
allStartFailures.push(...startFailures);
|
|
4146
|
+
const pollJob = async (jobId) => {
|
|
4147
|
+
const deadline = Date.now() + jobTimeoutMs;
|
|
4148
|
+
while (Date.now() < deadline) {
|
|
4149
|
+
const body = await fetchJson(resolveJobHref(jobId));
|
|
4150
|
+
const job = body.job;
|
|
4151
|
+
if (!job) {
|
|
4152
|
+
throw new Error(`Recovery job ${jobId} was not found.`);
|
|
4153
|
+
}
|
|
4154
|
+
if (job.status === "pass" || job.status === "fail") {
|
|
4155
|
+
return job;
|
|
4156
|
+
}
|
|
4157
|
+
await sleepVoiceRealCallProfileRecoveryLoop(jobPollMs);
|
|
4158
|
+
}
|
|
4159
|
+
throw new Error(`Timed out waiting ${String(jobTimeoutMs)}ms for recovery job ${jobId}.`);
|
|
4160
|
+
};
|
|
4161
|
+
options.logger?.log(`Polling ${String(startedJobs.length)} recovery job(s) in parallel.`);
|
|
4162
|
+
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
4163
|
+
const jobs = jobResults.map((result, index) => ({
|
|
4164
|
+
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
4165
|
+
jobId: startedJobs[index]?.jobId,
|
|
4166
|
+
result: result.status === "fulfilled" ? result.value : {
|
|
4167
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
4168
|
+
status: "fail"
|
|
4169
|
+
}
|
|
4170
|
+
}));
|
|
4171
|
+
allJobs.push(...jobs);
|
|
4172
|
+
if (refreshHref !== false) {
|
|
4173
|
+
await fetchJson(refreshHref, { method: "POST" });
|
|
4149
4174
|
}
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
const jobResults = await Promise.allSettled(startedJobs.map((start) => pollJob(start.jobId)));
|
|
4154
|
-
const jobs = jobResults.map((result, index) => ({
|
|
4155
|
-
action: describeVoiceRealCallProfileRecoveryLoopAction(startedJobs[index]?.action ?? {}),
|
|
4156
|
-
jobId: startedJobs[index]?.jobId,
|
|
4157
|
-
result: result.status === "fulfilled" ? result.value : {
|
|
4158
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
4159
|
-
status: "fail"
|
|
4175
|
+
realCallProfileGate = await getGate(true);
|
|
4176
|
+
if (realCallProfileGate?.status === "pass") {
|
|
4177
|
+
break;
|
|
4160
4178
|
}
|
|
4161
|
-
}));
|
|
4162
|
-
if (refreshHref !== false) {
|
|
4163
|
-
await fetchJson(refreshHref, { method: "POST" });
|
|
4164
4179
|
}
|
|
4165
|
-
const realCallProfileGate = await getGate(true);
|
|
4166
4180
|
return {
|
|
4167
|
-
actionCount: actions.length,
|
|
4181
|
+
actionCount: actions.length * passes,
|
|
4168
4182
|
actions,
|
|
4169
|
-
jobs,
|
|
4170
|
-
|
|
4183
|
+
jobs: allJobs,
|
|
4184
|
+
passes,
|
|
4185
|
+
ok: allStartFailures.length === 0 && allJobs.every((job) => job.result.status === "pass") && realCallProfileGate?.status === "pass",
|
|
4171
4186
|
realCallProfileGate,
|
|
4172
|
-
startFailures
|
|
4187
|
+
startFailures: allStartFailures
|
|
4173
4188
|
};
|
|
4174
4189
|
};
|
|
4175
4190
|
var buildVoiceRealCallProfileRecoveryActions = (report, options = {}) => {
|