refactor: split brokerage operations repository and cursor codec (WealthLedger/backend#167) (#190)
This commit was merged in pull request #190.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { type OperationInterval,
|
||||
operationIntervalsOverlap,
|
||||
operationsSyncPriority } from './operations-sync-plan';
|
||||
|
||||
export type OperationsIntent = {
|
||||
atomic: boolean;
|
||||
atomicIntervals?: string[];
|
||||
intervals: string[];
|
||||
screenIntervals?: string[];
|
||||
};
|
||||
|
||||
export function intervalKey(interval: OperationInterval): string {
|
||||
// eslint-disable-next-line sonarjs/no-inverted-boolean-check -- Negation also rejects Invalid Date; >= would silently accept NaN.
|
||||
if (!(interval.from < interval.to)) {
|
||||
throw new Error('Invalid operations interval');
|
||||
}
|
||||
return JSON.stringify([
|
||||
interval.accountId,
|
||||
interval.from.toISOString(),
|
||||
interval.to.toISOString(),
|
||||
interval.instrumentUid ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
export function decodeInterval(key: string): OperationInterval {
|
||||
const [accountId, from, to, instrumentUid] = JSON.parse(key) as string[];
|
||||
return {
|
||||
accountId,
|
||||
from: new Date(from),
|
||||
to: new Date(to),
|
||||
...(instrumentUid ? { instrumentUid } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function extendRunningIntent(input: {
|
||||
additions: OperationInterval[];
|
||||
intervals: OperationInterval[];
|
||||
pending: OperationInterval[];
|
||||
previous: OperationsIntent | undefined;
|
||||
previousPriority: number;
|
||||
priority: number;
|
||||
publicationAtomic: boolean;
|
||||
}): OperationsIntent {
|
||||
const { previous, pending, additions, intervals, priority, previousPriority, publicationAtomic } = input;
|
||||
const overlapsRequested = (item: OperationInterval) =>
|
||||
intervals.some((target) => operationIntervalsOverlap(item, target));
|
||||
const retainedScreen = previous?.screenIntervals ??
|
||||
(previousPriority === operationsSyncPriority.screen ? (previous?.intervals ?? []) : []);
|
||||
const addedScreen = priority === operationsSyncPriority.screen
|
||||
? [...pending, ...additions].filter(overlapsRequested).map(intervalKey)
|
||||
: [];
|
||||
const ordered = priority < previousPriority
|
||||
? [
|
||||
...pending.filter(overlapsRequested),
|
||||
...additions,
|
||||
...pending.filter((item) => !overlapsRequested(item)),
|
||||
]
|
||||
: [...pending, ...additions];
|
||||
return {
|
||||
atomic: previous?.atomic ?? publicationAtomic,
|
||||
atomicIntervals: previous?.atomic
|
||||
? [...new Set([...(previous.atomicIntervals ?? previous.intervals), ...additions.map(intervalKey)])]
|
||||
: [],
|
||||
screenIntervals: [...new Set([...retainedScreen, ...addedScreen])],
|
||||
intervals: ordered.map(intervalKey),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user