Skip to content

Commit bd1e4e1

Browse files
committed
fix(testing-drivers): stop polling once the pre-aggregation build has settled
The `failure` branch rejected from inside the status tally, where a `failure` status is neither `done` nor `missing_partition`, so `inProcess` stayed non-empty and neither timer was cleared. The helper went on POSTing to the jobs endpoint once a second for the remaining ~120s after the promise had settled, then the backstop called reject on an already-settled promise. `--forceExit` kept that from stalling the run, but it interleaved the polling output with every following test at exactly the moment someone is reading it to find out why the build failed. Hoist the check out of the loop so it settles and stops, and route every settle path through one `stop()` that clears both timers - the two guarded rejects added in the previous commit cleared the interval but left the 120s backstop pending. Postgres driver suite re-run green: 127 passed, 20 skipped, pre-aggregations still building. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDVoT5YNCrewPZ87jyzmkF
1 parent 6283c6b commit bd1e4e1

1 file changed

Lines changed: 24 additions & 7 deletions

File tree

packages/cubejs-testing-drivers/src/helpers/buildPreaggs.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export async function buildPreaggs(
8686
return;
8787
}
8888
let timeout: NodeJS.Timeout;
89+
// Every path that settles the outer promise goes through this, so neither the
90+
// poll nor the backstop outlives the result.
91+
let stop: () => void;
8992
const interval = setInterval(async () => {
9093
const inProcess = [];
9194
let statusBody = '';
@@ -104,7 +107,7 @@ export async function buildPreaggs(
104107
statusBody = (await readData(get)).toString();
105108
statuses = JSON.parse(statusBody);
106109
} catch (e) {
107-
clearInterval(interval);
110+
stop();
108111
reject(`Cube pre-aggregations build failed: ${statusBody || e}`);
109112
return;
110113
}
@@ -113,26 +116,40 @@ export async function buildPreaggs(
113116
// interval and leave the build to fail by timeout with the actual cause
114117
// never surfacing. Reject with the body instead.
115118
if (statuses.error) {
116-
clearInterval(interval);
119+
stop();
117120
reject(`Cube pre-aggregations build failed: ${statusBody}`);
118121
return;
119122
}
123+
// Checked before the tally rather than inside it: a `failure` status is
124+
// neither `done` nor `missing_partition`, so rejecting from within the loop
125+
// left `inProcess` non-empty and both timers armed, and the helper went on
126+
// polling for the remaining ~120s after the promise had already settled -
127+
// interleaving its noise with the output someone is reading to find out why
128+
// the build failed.
129+
const failed = Object.keys(statuses).find(
130+
(t: string) => statuses[t].status.indexOf('failure') >= 0
131+
);
132+
if (failed) {
133+
stop();
134+
reject(`Cube pre-aggregations build failed: ${statuses[failed].status}`);
135+
return;
136+
}
120137
Object.keys(statuses).forEach((t: string) => {
121138
const { status } = statuses[t];
122-
if (status.indexOf('failure') >= 0) {
123-
reject(`Cube pre-aggregations build failed: ${status}`);
124-
}
125139
if (status !== 'done' && status !== 'missing_partition') {
126140
inProcess.push(t);
127141
}
128142
});
129143
if (inProcess.length === 0) {
130-
clearInterval(interval);
131-
clearTimeout(timeout);
144+
stop();
132145
resolve(true);
133146
}
134147
}, 1000);
135148

149+
stop = () => {
150+
clearInterval(interval);
151+
clearTimeout(timeout);
152+
};
136153
timeout = setTimeout(() => {
137154
clearInterval(interval);
138155
reject('Cube pre-aggregations build failed: timeout.');

0 commit comments

Comments
 (0)