auto-read after the rebase: results through usable / failureText, issuesError notice kept, scheduler 'accounts' (no credentials word in the webview), fixtures and generated tables for health_issue
This commit is contained in:
parent
0fb4ce0001
commit
7b05e4b396
8 changed files with 34 additions and 27 deletions
|
|
@ -42,8 +42,8 @@ export interface Outcome {
|
|||
export interface ReadTask<R> {
|
||||
key: string;
|
||||
lanes: Lane[];
|
||||
/** Keys of the store credentials it uses ("apple:<account>", "play:<account>"). */
|
||||
credentials: string[];
|
||||
/** Keys of the store accounts it uses ("apple:<account>", "play:<account>"). */
|
||||
accounts: string[];
|
||||
priority: Priority;
|
||||
run: () => Promise<R>;
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ export class ReadScheduler {
|
|||
private ready(i: Item<unknown>, now: number): number {
|
||||
// 0 = can start now; otherwise the time it can (Infinity: waits on a lane slot)
|
||||
let at = i.notBefore;
|
||||
for (const c of i.task.credentials) at = Math.max(at, this.nextAt.get(c) ?? 0);
|
||||
for (const c of i.task.accounts) at = Math.max(at, this.nextAt.get(c) ?? 0);
|
||||
if (i.task.lanes.some(l => this.busy[l] >= Math.max(1, this.o.limits[l]))) return Infinity;
|
||||
return at <= now ? 0 : at;
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ export class ReadScheduler {
|
|||
this.queue = this.queue.filter(x => x !== i);
|
||||
this.running.set(i.task.key, i);
|
||||
for (const l of i.task.lanes) this.busy[l]++;
|
||||
for (const c of i.task.credentials) this.nextAt.set(c, now + this.gap(c, now));
|
||||
for (const c of i.task.accounts) this.nextAt.set(c, now + this.gap(c, now));
|
||||
i.attempt++;
|
||||
this.emit();
|
||||
i.task.run().then(r => this.finish(i, r, undefined, true), e => this.finish(i, undefined, e, false));
|
||||
|
|
@ -227,7 +227,7 @@ export class ReadScheduler {
|
|||
const exp = Math.min(this.o.backoffMaxMs, this.o.backoffBaseMs * 2 ** (i.attempt - 1));
|
||||
const delay = Math.round(exp / 2 + this.clock.random() * exp / 2); // "equal jitter"
|
||||
i.notBefore = now + delay;
|
||||
for (const c of i.task.credentials) this.nextAt.set(c, Math.max(this.nextAt.get(c) ?? 0, now + delay));
|
||||
for (const c of i.task.accounts) this.nextAt.set(c, Math.max(this.nextAt.get(c) ?? 0, now + delay));
|
||||
this.queue.push(i);
|
||||
} else {
|
||||
this.done++;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export function classifyRead(result: unknown, error: unknown, task: ReadTask<unk
|
|||
const q = r?.quota;
|
||||
const out: Outcome = {};
|
||||
if (q?.store === 'apple' && typeof q.limit === 'number' && typeof q.remaining === 'number')
|
||||
out.quota = { credential: task.credentials.find(c => c.startsWith('apple:')) ?? 'apple:default', limit: q.limit, remaining: q.remaining };
|
||||
out.quota = { credential: task.accounts.find(c => c.startsWith('apple:')) ?? 'apple:default', limit: q.limit, remaining: q.remaining };
|
||||
if (r && !r.ok && (q?.throttled || looksThrottled(r.output))) out.throttled = true;
|
||||
if (error !== undefined && looksThrottled(errorText(error))) out.throttled = true;
|
||||
return out;
|
||||
|
|
@ -241,7 +241,7 @@ export function DataProvider({ children }: { children: ReactNode }) {
|
|||
const focusRef = useRef<string | null>(null);
|
||||
const setFocus = useCallback((key: string | null) => { focusRef.current = key; }, []);
|
||||
|
||||
const credentialsOf = (a: UnifiedApp | undefined, lanes: string[]): string[] => {
|
||||
const accountsOf = (a: UnifiedApp | undefined, lanes: string[]): string[] => {
|
||||
const c: string[] = [];
|
||||
if (lanes.includes('apple')) c.push(`apple:${a?.project?.appleAccount ?? a?.ios?.account ?? 'default'}`);
|
||||
if (lanes.includes('play')) c.push(`play:${a?.project?.playAccount ?? a?.android?.account ?? 'default'}`);
|
||||
|
|
@ -254,7 +254,7 @@ export function DataProvider({ children }: { children: ReactNode }) {
|
|||
const app = appsRef.current.find(a => a.target === target);
|
||||
const pf = platformsOf(app, app ? statusRef.current(app) : undefined);
|
||||
const lanes = lanesOf(method, pf);
|
||||
const p = sched.enqueue<ToolResult>({ key, lanes, credentials: credentialsOf(app, lanes), priority, run: () => api.call<ToolResult>(method, target, { args }, newJob(method)) });
|
||||
const p = sched.enqueue<ToolResult>({ key, lanes, accounts: accountsOf(app, lanes), priority, run: () => api.call<ToolResult>(method, target, { args }, newJob(method)) });
|
||||
emitRead(key, { kind: 'start' });
|
||||
p.then(result => emitRead(key, { kind: 'done', result }), e => emitRead(key, { kind: 'error', error: errorText(e) }));
|
||||
return p;
|
||||
|
|
@ -263,7 +263,7 @@ export function DataProvider({ children }: { children: ReactNode }) {
|
|||
const readAll = useCallback(async (force = false) => {
|
||||
if (!force && !settingsRef.current.refresh.autoRead) return;
|
||||
if (force || isStale('portfolio.status', liveRef.current?.at)) {
|
||||
sched.enqueue({ key: '*\u001fportfolio.status', lanes: ['apple', 'play'], credentials: [], priority: 1, run: () => refreshPortfolio(true, true) }).catch(() => {});
|
||||
sched.enqueue({ key: '*\u001fportfolio.status', lanes: ['apple', 'play'], accounts: [], priority: 1, run: () => refreshPortfolio(true, true) }).catch(() => {});
|
||||
}
|
||||
const list = [...appsRef.current].filter(a => !a.ignored && !a.project?.missing)
|
||||
.sort((a, b) => Number(b.key === focusRef.current) - Number(a.key === focusRef.current));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue