Skip to content
Source
Sign inSign up

pullRequestStatsPersistence.ts

48 lines1.9 KB

1import {
2 PullRequestDiffStat,
3 PullRequestListStatsInput,
4 type PullRequestListStatsResult,
5 type PullRequestRef,
6} from "@t3tools/contracts";
7import * as Effect from "effect/Effect";
8import * as Option from "effect/Option";
9import * as Schema from "effect/Schema";
10import { persistQuery, type QueryPersistence } from "./queryPersistence.ts";
11​
12const requestKey = Schema.fromJsonString(Schema.Tuple([Schema.String, PullRequestListStatsInput]));
13const statKey = (ref: PullRequestRef) =>
14 JSON.stringify(["pull-request-stat", ref.projectId, ref.host ?? "", ref.repository, ref.number]);
15​
16export function persistPullRequestStats(): QueryPersistence<PullRequestListStatsResult> {
17 const row = persistQuery(PullRequestDiffStat);
18 return {
19 load: Effect.fn("pullRequestStatsPersistence.load")(
20 function* (environmentId, key) {
21 const [, input] = yield* Schema.decodeEffect(requestKey)(key);
22 const rows = yield* Effect.forEach(
23 input.refs,
24 (ref) => row.load(environmentId, statKey(ref)),
25 { concurrency: "unbounded" },
26 );
27 const stats = rows.flatMap((value) => (Option.isSome(value) ? [value.value] : []));
28 return stats.length ? Option.some({ stats }) : Option.none();
29 },
30 Effect.orElseSucceed(() => Option.none()),
31 ),
32 save: Effect.fn("pullRequestStatsPersistence.save")(
33 function* (environmentId, key, result) {
34 const [, input] = yield* Schema.decodeEffect(requestKey)(key);
35 yield* Effect.forEach(result.stats, (stat) => {
36 const ref = input.refs.find(
37 (ref) =>
38 ref.projectId === stat.projectId &&
39 ref.repository === stat.repository &&
40 ref.number === stat.number,
41 );
42 return ref ? row.save(environmentId, statKey(ref), stat) : Effect.void;
43 });
44 },
45 (effect, _environmentId, _key, _result) => effect.pipe(Effect.ignore),
46 ),
47 };