Skip to content

Commit 1cccf1b

Browse files
Merge pull request #30 from viamrobotics/better-polling
Only poll once request roundtrips have finished
2 parents 890ad2c + 2ae1ae6 commit 1cccf1b

File tree

6 files changed

+67
-4
lines changed

6 files changed

+67
-4
lines changed

.changeset/seven-bags-switch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@viamrobotics/svelte-sdk': minor
3+
---
4+
5+
Only poll once request round trips have finished

src/lib/hooks/create-resource-query.svelte.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from '@tanstack/svelte-query';
66
import type { Resource } from '@viamrobotics/sdk';
77
import { toStore, fromStore } from 'svelte/store';
8+
import { usePolling } from './use-polling.svelte';
89

910
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1011
export type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
@@ -35,7 +36,7 @@ export const createResourceQuery = <T extends Resource, K extends keyof T>(
3536
): { current: QueryObserverResult<ResolvedReturnType<T[K]>> } => {
3637
let [args, options] = additional;
3738

38-
if (options === undefined) {
39+
if (options === undefined && args !== undefined) {
3940
options = args as QueryOptions;
4041
args = undefined;
4142
}
@@ -72,8 +73,14 @@ export const createResourceQuery = <T extends Resource, K extends keyof T>(
7273
>;
7374
},
7475
..._options,
76+
refetchInterval: false,
7577
})
7678
);
7779

80+
usePolling(
81+
() => queryOptions.queryKey,
82+
() => _options?.refetchInterval ?? false
83+
);
84+
7885
return fromStore(createQuery(toStore(() => queryOptions)));
7986
};

src/lib/hooks/create-robot-query.svelte.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66

77
import type { RobotClient } from '@viamrobotics/sdk';
88
import { toStore, fromStore } from 'svelte/store';
9+
import { usePolling } from './use-polling.svelte';
910

1011
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1112
export type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
@@ -36,7 +37,7 @@ export const createRobotQuery = <T extends RobotClient, K extends keyof T>(
3637
): { current: QueryObserverResult<ResolvedReturnType<T[K]>> } => {
3738
let [args, options] = additional;
3839

39-
if (options === undefined) {
40+
if (options === undefined && args !== undefined) {
4041
options = args as QueryOptions;
4142
args = undefined;
4243
}
@@ -73,8 +74,14 @@ export const createRobotQuery = <T extends RobotClient, K extends keyof T>(
7374
>;
7475
},
7576
..._options,
77+
refetchInterval: false,
7678
})
7779
);
7880

81+
usePolling(
82+
() => queryOptions.queryKey,
83+
() => _options?.refetchInterval ?? false
84+
);
85+
7986
return fromStore(createQuery(toStore(() => queryOptions)));
8087
};

src/lib/hooks/machine-status.svelte.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { getContext, setContext } from 'svelte';
99
import type { PartID } from '$lib/part';
1010
import type { RobotClient } from '@viamrobotics/sdk';
11+
import { usePolling } from './use-polling.svelte';
1112

1213
const key = Symbol('machine-status-context');
1314

@@ -30,13 +31,14 @@ export const provideMachineStatusContext = (refetchInterval: () => number) => {
3031
'partID',
3132
partID,
3233
'robotClient',
33-
'machineStatus',
34+
'getMachineStatus',
3435
],
35-
refetchInterval: refetchInterval(),
36+
refetchInterval: false,
3637
queryFn: async (): Promise<MachineStatus> => {
3738
if (!client) {
3839
throw new Error('No client');
3940
}
41+
4042
return client.getMachineStatus();
4143
},
4244
});
@@ -55,6 +57,12 @@ export const provideMachineStatusContext = (refetchInterval: () => number) => {
5557
})
5658
);
5759

60+
$effect(() => {
61+
for (const option of options) {
62+
usePolling(() => option.queryKey, refetchInterval);
63+
}
64+
});
65+
5866
setContext(key, {
5967
get current() {
6068
return queries.current;

src/lib/hooks/resource-names.svelte.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const provideResourceNamesContext = () => {
4848
if (!client) {
4949
throw new Error('No client');
5050
}
51+
5152
return client.resourceNames();
5253
},
5354
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useQueryClient } from '@tanstack/svelte-query';
2+
3+
/**
4+
* Polls a query at an interval while waiting for
5+
* a round trip to conclude before restarting the interval
6+
* countdown.
7+
*
8+
* The result is that if a viam server becomes unresponsive,
9+
* requests will not begin to stack, exacerbating issues.
10+
*/
11+
export function usePolling(
12+
queryKey: () => unknown[],
13+
interval: () => number | false
14+
) {
15+
const queryClient = useQueryClient();
16+
let timeoutId: ReturnType<typeof setTimeout>;
17+
18+
$effect(() => {
19+
const key = queryKey();
20+
const currentInterval = interval();
21+
22+
if (!currentInterval) {
23+
return;
24+
}
25+
26+
const poll = async () => {
27+
await queryClient.refetchQueries({ queryKey: key });
28+
timeoutId = setTimeout(poll, currentInterval);
29+
};
30+
31+
timeoutId = setTimeout(poll, currentInterval);
32+
33+
return () => clearTimeout(timeoutId);
34+
});
35+
}

0 commit comments

Comments
 (0)