Skip to content

Commit 84b7030

Browse files
committed
feature: tag[0] 기반 파티셔닝 전략 도입
1 parent 59e0522 commit 84b7030

3 files changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import type { CanonicalSpec } from "@patchlogr/types";
2+
import { describe, expect, test } from "vitest";
3+
import { partitionByTag } from "../partitionByTag";
4+
5+
describe("partitionByTag", () => {
6+
test("should group by first tag", () => {
7+
const spec: CanonicalSpec = {
8+
operations: {
9+
"GET /user": {
10+
key: "GET /user",
11+
doc: { tags: ["user"] },
12+
method: "GET",
13+
path: "/user",
14+
request: { params: [] },
15+
responses: {},
16+
},
17+
"GET /user/{userId}": {
18+
key: "GET /user/{userId}",
19+
doc: { tags: ["user"] },
20+
method: "GET",
21+
path: "/user/{userId}",
22+
request: { params: [] },
23+
responses: {},
24+
},
25+
},
26+
};
27+
28+
const partitions = partitionByTag(spec).partitions;
29+
expect(partitions).toHaveLength(1);
30+
expect(partitions.get("user")).toHaveLength(2);
31+
expect(partitions.get("user")?.[0]?.operationKey).toBe("GET /user");
32+
expect(partitions.get("user")?.[1]?.operationKey).toBe(
33+
"GET /user/{userId}",
34+
);
35+
});
36+
37+
test("should group by multiple tags", () => {
38+
const spec: CanonicalSpec = {
39+
operations: {
40+
"GET /user": {
41+
key: "GET /user",
42+
doc: { tags: ["user"] },
43+
method: "GET",
44+
path: "/user",
45+
request: { params: [] },
46+
responses: {},
47+
},
48+
"POST /auth/login": {
49+
key: "POST /auth/login",
50+
doc: { tags: ["auth"] },
51+
method: "POST",
52+
path: "/auth/login",
53+
request: { params: [] },
54+
responses: {},
55+
},
56+
},
57+
};
58+
59+
const partitions = partitionByTag(spec).partitions;
60+
61+
expect(partitions).toHaveLength(2);
62+
expect(partitions.get("user")).toHaveLength(1);
63+
expect(partitions.get("auth")).toHaveLength(1);
64+
expect(partitions.get("user")?.[0]?.operationKey).toBe("GET /user");
65+
expect(partitions.get("auth")?.[0]?.operationKey).toBe(
66+
"POST /auth/login",
67+
);
68+
});
69+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export type PartitionManifest = {
2+
key: string;
3+
hash: string;
4+
};
5+
6+
export type Partition = {
7+
hash: string;
8+
operationKey: string;
9+
};
10+
11+
export type PartitionedSpec = {
12+
metadata: Record<string, unknown>;
13+
partitions: Map<string, Partition[]>;
14+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { CanonicalSpec } from "@patchlogr/types";
2+
import type { Partition, PartitionedSpec } from "./partition";
3+
4+
import { createSHA256Hash } from "../utils/createHash";
5+
import { stableStringify } from "../utils/stableStringify";
6+
7+
const DEFAULT_TAG = "__DEFAULT__";
8+
9+
export function partitionByTag(spec: CanonicalSpec): PartitionedSpec {
10+
const partitions = new Map<string, Partition[]>();
11+
12+
Object.entries(spec.operations).forEach(([key, operation]) => {
13+
const tag = operation.doc?.tags?.[0] || DEFAULT_TAG;
14+
const hash = createSHA256Hash(stableStringify(operation));
15+
16+
if (!partitions.has(tag))
17+
partitions.set(tag, [{ hash, operationKey: key }]);
18+
else partitions.get(tag)?.push({ hash, operationKey: key });
19+
});
20+
21+
return {
22+
metadata: {
23+
...spec.info,
24+
...spec.security,
25+
},
26+
partitions,
27+
};
28+
}

0 commit comments

Comments
 (0)