Skip to content

Commit 3e290ef

Browse files
authored
RAI-11434 refactor polling transaction logic (#87)
* RAI-11434 refactor polling transaction logic * refactor * match julia sdk * fix ts * refactor * refactor * fix types * remove unused assertion * address feedback * remove try/catch * address feedback * wrap with try/catch
1 parent 15496ee commit 3e290ef

File tree

4 files changed

+74
-51
lines changed

4 files changed

+74
-51
lines changed

src/api/query/execAsyncApi.ts

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@
1414
* under the License.
1515
*/
1616

17-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
18-
17+
import { PollOptions, pollWithOverhead } from '../../rest';
1918
import { TransactionAsyncApi } from '../transaction/transactionAsyncApi';
2019
import {
2120
isTransactionDone,
2221
makeArrowRelations,
2322
} from '../transaction/transactionUtils';
2423
import {
25-
TransactionAsyncCompact,
24+
TransactionAsync,
2625
TransactionAsyncPayload,
2726
TransactionAsyncResult,
2827
} from '../transaction/types';
@@ -61,8 +60,7 @@ export class ExecAsyncApi extends TransactionAsyncApi {
6160
inputs: QueryInput[] = [],
6261
readonly = true,
6362
tags: string[] = [],
64-
interval = 1000, // 1 second
65-
timeout = Number.POSITIVE_INFINITY,
63+
options?: PollOptions,
6664
) {
6765
const result = await this.execAsync(
6866
database,
@@ -78,59 +76,38 @@ export class ExecAsyncApi extends TransactionAsyncApi {
7876
return result;
7977
}
8078

81-
return await this.pollTransaction(txnId, interval, timeout);
79+
return await this.pollTransaction(txnId, options);
8280
}
8381

8482
async pollTransaction(
8583
txnId: string,
86-
interval = 1000,
87-
timeout = Number.POSITIVE_INFINITY,
88-
) {
89-
const startedAt = Date.now();
90-
91-
let transaction: TransactionAsyncCompact | undefined;
92-
93-
await new Promise<void>((resolve, reject) => {
94-
const checkState = () => {
95-
setTimeout(async () => {
96-
try {
97-
transaction = await this.getTransaction(txnId);
98-
// eslint-disable-next-line no-empty
99-
} catch {}
100-
101-
if (transaction && isTransactionDone(transaction.state)) {
102-
resolve();
103-
} else {
104-
if (Date.now() - startedAt > timeout) {
105-
reject(
106-
new Error(
107-
`Polling transaction timeout of ${timeout}ms has been exceeded.`,
108-
),
109-
);
110-
}
111-
112-
checkState();
113-
}
114-
}, interval);
84+
options?: PollOptions,
85+
): Promise<TransactionAsyncResult> {
86+
const transaction = await pollWithOverhead<TransactionAsync>(async () => {
87+
const transaction = await this.getTransaction(txnId);
88+
if (isTransactionDone(transaction.state)) {
89+
return {
90+
done: true,
91+
result: transaction,
92+
};
93+
}
94+
95+
return {
96+
done: false,
11597
};
116-
117-
checkState();
118-
});
98+
}, options);
11999

120100
const data = await Promise.all([
121101
this.getTransactionMetadata(txnId),
122102
this.getTransactionProblems(txnId),
123103
this.getTransactionResults(txnId),
124104
]);
125-
const results = await makeArrowRelations(data[2], data[0]);
126105

127-
const res: TransactionAsyncResult = {
128-
transaction: transaction!,
106+
return {
107+
transaction,
129108
problems: data[1],
130-
results,
109+
results: makeArrowRelations(data[2], data[0]),
131110
};
132-
133-
return res;
134111
}
135112

136113
async loadJson(

src/api/transaction/transactionUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
TransactionAsyncFile,
2727
TransactionAsyncResult,
2828
TransactionAsyncState,
29-
} from '../transaction/types';
29+
} from './types';
3030

3131
export function makeLabeledAction(
3232
name: string,
@@ -105,7 +105,7 @@ export async function readArrowFiles(files: TransactionAsyncFile[]) {
105105
return results;
106106
}
107107

108-
export async function makeArrowRelations(
108+
export function makeArrowRelations(
109109
results: ArrowResult[],
110110
metadata?: MetadataInfo,
111111
) {

src/rest.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ export type RequestOptions = {
3333
onResponse?: (r: ApiResponse) => void;
3434
};
3535

36+
export type PollOptions = {
37+
overheadRate?: number;
38+
maxInterval?: number;
39+
timeout?: number;
40+
};
41+
42+
export type PollingResult<T> = {
43+
done: boolean;
44+
result?: T;
45+
};
46+
3647
function addDefaultHeaders(headers: RequestInit['headers'], url: string) {
3748
const sdkUserAgent = `rai-sdk-javascript/${VERSION}`;
3849
const defaultHeaders: RequestInit['headers'] = {
@@ -150,3 +161,40 @@ function responseToInfo(response: Response, body: any) {
150161

151162
return info;
152163
}
164+
165+
export async function pollWithOverhead<T = void>(
166+
callback: () => PollingResult<T> | PromiseLike<PollingResult<T>>,
167+
options?: PollOptions,
168+
) {
169+
const overheadRate = options?.overheadRate ?? 0.1;
170+
const startTime = Date.now();
171+
const timeout = options?.timeout ?? Number.POSITIVE_INFINITY;
172+
const maxInterval = options?.maxInterval ?? 120000;
173+
return new Promise<T>((resolve, reject) => {
174+
const poll = (delay: number) => {
175+
setTimeout(async () => {
176+
try {
177+
const pollingResult = await callback();
178+
if (pollingResult.done && pollingResult.result) {
179+
resolve(pollingResult.result);
180+
return;
181+
}
182+
} catch (error: any) {
183+
reject(error);
184+
return;
185+
}
186+
187+
const currentDelay = Date.now() - startTime;
188+
if (currentDelay > timeout) {
189+
reject(
190+
new Error(`Polling timeout of ${timeout}ms has been exceeded.`),
191+
);
192+
return;
193+
}
194+
poll(Math.min(maxInterval, currentDelay * overheadRate));
195+
}, delay);
196+
};
197+
198+
poll(Math.min(maxInterval, (Date.now() - startTime) * overheadRate));
199+
});
200+
}

src/testUtils.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,9 @@ function logifyClient(client: Client) {
270270
client.pollTransaction = async (...args) => {
271271
testLog(`polling transaction ${args[0]}`);
272272

273-
return await pollTransaction(
274-
args[0],
275-
args[1],
276-
timeout ? Number(timeout) : 120000,
277-
);
273+
return await pollTransaction(args[0], {
274+
timeout: timeout ? Number(timeout) : 120000,
275+
});
278276
};
279277
}
280278

0 commit comments

Comments
 (0)