@takaro/db 0.4.10 → 0.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/migrations/sql/20251220000000-inventory-diff-storage.d.ts +4 -0
- package/dist/migrations/sql/20251220000000-inventory-diff-storage.d.ts.map +1 -0
- package/dist/migrations/sql/20251220000000-inventory-diff-storage.js +147 -0
- package/dist/migrations/sql/20251220000000-inventory-diff-storage.js.map +1 -0
- package/package.json +19 -8
- package/src/migrations/sql/20251220000000-inventory-diff-storage.ts +164 -0
- package/tsconfig.build.json +6 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20251220000000-inventory-diff-storage.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20251220000000-inventory-diff-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA0JlD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export async function up(knex) {
|
|
2
|
+
// Create playerInventoryBaseline table - full inventory snapshots every hour
|
|
3
|
+
await knex.raw(`
|
|
4
|
+
CREATE TABLE "playerInventoryBaseline" (
|
|
5
|
+
id UUID DEFAULT gen_random_uuid() NOT NULL,
|
|
6
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
7
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
8
|
+
domain VARCHAR(255) NOT NULL,
|
|
9
|
+
"playerId" UUID NOT NULL,
|
|
10
|
+
"baselineId" UUID NOT NULL,
|
|
11
|
+
"itemId" UUID NOT NULL,
|
|
12
|
+
quantity INTEGER NOT NULL,
|
|
13
|
+
quality VARCHAR(255),
|
|
14
|
+
CONSTRAINT "playerInventoryBaseline_pkey" PRIMARY KEY ("createdAt", "baselineId", "itemId"),
|
|
15
|
+
CONSTRAINT "playerInventoryBaseline_domain_foreign" FOREIGN KEY (domain) REFERENCES domains(id) ON DELETE CASCADE,
|
|
16
|
+
CONSTRAINT "playerInventoryBaseline_playerId_foreign" FOREIGN KEY ("playerId") REFERENCES "playerOnGameServer"(id) ON DELETE CASCADE,
|
|
17
|
+
CONSTRAINT "playerInventoryBaseline_itemId_foreign" FOREIGN KEY ("itemId") REFERENCES items(id) ON DELETE CASCADE,
|
|
18
|
+
CONSTRAINT "playerInventoryBaseline_quantity_check" CHECK (quantity >= 0)
|
|
19
|
+
) PARTITION BY RANGE ("createdAt")
|
|
20
|
+
`);
|
|
21
|
+
// Create playerInventoryDiff table - individual item changes between baselines
|
|
22
|
+
await knex.raw(`
|
|
23
|
+
CREATE TABLE "playerInventoryDiff" (
|
|
24
|
+
id UUID DEFAULT gen_random_uuid() NOT NULL,
|
|
25
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
26
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
27
|
+
domain VARCHAR(255) NOT NULL,
|
|
28
|
+
"playerId" UUID NOT NULL,
|
|
29
|
+
"itemId" UUID NOT NULL,
|
|
30
|
+
"changeType" VARCHAR(10) NOT NULL,
|
|
31
|
+
"previousQuantity" INTEGER,
|
|
32
|
+
"newQuantity" INTEGER,
|
|
33
|
+
"previousQuality" VARCHAR(255),
|
|
34
|
+
"newQuality" VARCHAR(255),
|
|
35
|
+
CONSTRAINT "playerInventoryDiff_pkey" PRIMARY KEY ("createdAt", "playerId", "itemId"),
|
|
36
|
+
CONSTRAINT "playerInventoryDiff_domain_foreign" FOREIGN KEY (domain) REFERENCES domains(id) ON DELETE CASCADE,
|
|
37
|
+
CONSTRAINT "playerInventoryDiff_playerId_foreign" FOREIGN KEY ("playerId") REFERENCES "playerOnGameServer"(id) ON DELETE CASCADE,
|
|
38
|
+
CONSTRAINT "playerInventoryDiff_itemId_foreign" FOREIGN KEY ("itemId") REFERENCES items(id) ON DELETE CASCADE,
|
|
39
|
+
CONSTRAINT "playerInventoryDiff_changeType_check" CHECK ("changeType" IN ('added', 'removed', 'changed'))
|
|
40
|
+
) PARTITION BY RANGE ("createdAt")
|
|
41
|
+
`);
|
|
42
|
+
// Create partition function for playerInventoryBaseline
|
|
43
|
+
await knex.raw(`
|
|
44
|
+
CREATE OR REPLACE FUNCTION ensure_player_inventory_baseline_partition(date_param VARCHAR DEFAULT NULL)
|
|
45
|
+
RETURNS VOID AS $$
|
|
46
|
+
DECLARE
|
|
47
|
+
current_day_start DATE;
|
|
48
|
+
next_day_start DATE;
|
|
49
|
+
partition_name TEXT;
|
|
50
|
+
partition_exists BOOLEAN;
|
|
51
|
+
target_date DATE;
|
|
52
|
+
BEGIN
|
|
53
|
+
IF date_param IS NOT NULL THEN
|
|
54
|
+
target_date := DATE(date_param::TIMESTAMP);
|
|
55
|
+
ELSE
|
|
56
|
+
target_date := CURRENT_DATE;
|
|
57
|
+
END IF;
|
|
58
|
+
|
|
59
|
+
current_day_start := DATE_TRUNC('day', target_date);
|
|
60
|
+
next_day_start := current_day_start + INTERVAL '1 day';
|
|
61
|
+
|
|
62
|
+
partition_name := 'playerInventoryBaseline_' || TO_CHAR(current_day_start, 'YYYY_MM_DD');
|
|
63
|
+
|
|
64
|
+
SELECT EXISTS (
|
|
65
|
+
SELECT 1 FROM pg_class c
|
|
66
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
67
|
+
WHERE c.relname = partition_name
|
|
68
|
+
AND n.nspname = 'public'
|
|
69
|
+
) INTO partition_exists;
|
|
70
|
+
|
|
71
|
+
IF NOT partition_exists THEN
|
|
72
|
+
EXECUTE format(
|
|
73
|
+
'CREATE TABLE %I PARTITION OF "playerInventoryBaseline"
|
|
74
|
+
FOR VALUES FROM (%L) TO (%L)',
|
|
75
|
+
partition_name,
|
|
76
|
+
current_day_start,
|
|
77
|
+
next_day_start
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
RAISE NOTICE 'Created partition: % for date: %',
|
|
81
|
+
partition_name, current_day_start;
|
|
82
|
+
END IF;
|
|
83
|
+
END;
|
|
84
|
+
$$ LANGUAGE plpgsql;
|
|
85
|
+
`);
|
|
86
|
+
// Create partition function for playerInventoryDiff
|
|
87
|
+
await knex.raw(`
|
|
88
|
+
CREATE OR REPLACE FUNCTION ensure_player_inventory_diff_partition(date_param VARCHAR DEFAULT NULL)
|
|
89
|
+
RETURNS VOID AS $$
|
|
90
|
+
DECLARE
|
|
91
|
+
current_day_start DATE;
|
|
92
|
+
next_day_start DATE;
|
|
93
|
+
partition_name TEXT;
|
|
94
|
+
partition_exists BOOLEAN;
|
|
95
|
+
target_date DATE;
|
|
96
|
+
BEGIN
|
|
97
|
+
IF date_param IS NOT NULL THEN
|
|
98
|
+
target_date := DATE(date_param::TIMESTAMP);
|
|
99
|
+
ELSE
|
|
100
|
+
target_date := CURRENT_DATE;
|
|
101
|
+
END IF;
|
|
102
|
+
|
|
103
|
+
current_day_start := DATE_TRUNC('day', target_date);
|
|
104
|
+
next_day_start := current_day_start + INTERVAL '1 day';
|
|
105
|
+
|
|
106
|
+
partition_name := 'playerInventoryDiff_' || TO_CHAR(current_day_start, 'YYYY_MM_DD');
|
|
107
|
+
|
|
108
|
+
SELECT EXISTS (
|
|
109
|
+
SELECT 1 FROM pg_class c
|
|
110
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
111
|
+
WHERE c.relname = partition_name
|
|
112
|
+
AND n.nspname = 'public'
|
|
113
|
+
) INTO partition_exists;
|
|
114
|
+
|
|
115
|
+
IF NOT partition_exists THEN
|
|
116
|
+
EXECUTE format(
|
|
117
|
+
'CREATE TABLE %I PARTITION OF "playerInventoryDiff"
|
|
118
|
+
FOR VALUES FROM (%L) TO (%L)',
|
|
119
|
+
partition_name,
|
|
120
|
+
current_day_start,
|
|
121
|
+
next_day_start
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
RAISE NOTICE 'Created partition: % for date: %',
|
|
125
|
+
partition_name, current_day_start;
|
|
126
|
+
END IF;
|
|
127
|
+
END;
|
|
128
|
+
$$ LANGUAGE plpgsql;
|
|
129
|
+
`);
|
|
130
|
+
// Create indexes for playerInventoryBaseline
|
|
131
|
+
await knex.raw(`CREATE INDEX "playerInventoryBaseline_domain_createdAt_idx" ON "playerInventoryBaseline" (domain, "createdAt")`);
|
|
132
|
+
await knex.raw(`CREATE INDEX "playerInventoryBaseline_playerId_idx" ON "playerInventoryBaseline" ("playerId")`);
|
|
133
|
+
await knex.raw(`CREATE INDEX "playerInventoryBaseline_playerId_createdAt_idx" ON "playerInventoryBaseline" ("playerId", "createdAt" DESC)`);
|
|
134
|
+
await knex.raw(`CREATE INDEX "playerInventoryBaseline_baselineId_idx" ON "playerInventoryBaseline" ("baselineId")`);
|
|
135
|
+
// Create indexes for playerInventoryDiff
|
|
136
|
+
await knex.raw(`CREATE INDEX "playerInventoryDiff_domain_createdAt_idx" ON "playerInventoryDiff" (domain, "createdAt")`);
|
|
137
|
+
await knex.raw(`CREATE INDEX "playerInventoryDiff_playerId_idx" ON "playerInventoryDiff" ("playerId")`);
|
|
138
|
+
await knex.raw(`CREATE INDEX "playerInventoryDiff_playerId_createdAt_idx" ON "playerInventoryDiff" ("playerId", "createdAt" DESC)`);
|
|
139
|
+
await knex.raw(`CREATE INDEX "playerInventoryDiff_itemId_createdAt_idx" ON "playerInventoryDiff" ("itemId", "createdAt" DESC)`);
|
|
140
|
+
}
|
|
141
|
+
export async function down(knex) {
|
|
142
|
+
await knex.raw('DROP FUNCTION IF EXISTS ensure_player_inventory_baseline_partition(VARCHAR)');
|
|
143
|
+
await knex.raw('DROP FUNCTION IF EXISTS ensure_player_inventory_diff_partition(VARCHAR)');
|
|
144
|
+
await knex.raw('DROP TABLE IF EXISTS "playerInventoryBaseline" CASCADE');
|
|
145
|
+
await knex.raw('DROP TABLE IF EXISTS "playerInventoryDiff" CASCADE');
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=20251220000000-inventory-diff-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20251220000000-inventory-diff-storage.js","sourceRoot":"","sources":["../../../src/migrations/sql/20251220000000-inventory-diff-storage.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,6EAA6E;IAC7E,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;GAiBd,CAAC,CAAC;IAEH,+EAA+E;IAC/E,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;GAmBd,CAAC,CAAC;IAEH,wDAAwD;IACxD,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0Cd,CAAC,CAAC;IAEH,oDAAoD;IACpD,MAAM,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0Cd,CAAC,CAAC;IAEH,6CAA6C;IAC7C,MAAM,IAAI,CAAC,GAAG,CACZ,gHAAgH,CACjH,CAAC;IACF,MAAM,IAAI,CAAC,GAAG,CAAC,+FAA+F,CAAC,CAAC;IAChH,MAAM,IAAI,CAAC,GAAG,CACZ,2HAA2H,CAC5H,CAAC;IACF,MAAM,IAAI,CAAC,GAAG,CAAC,mGAAmG,CAAC,CAAC;IAEpH,yCAAyC;IACzC,MAAM,IAAI,CAAC,GAAG,CACZ,wGAAwG,CACzG,CAAC;IACF,MAAM,IAAI,CAAC,GAAG,CAAC,uFAAuF,CAAC,CAAC;IACxG,MAAM,IAAI,CAAC,GAAG,CACZ,mHAAmH,CACpH,CAAC;IACF,MAAM,IAAI,CAAC,GAAG,CACZ,+GAA+G,CAChH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,GAAG,CAAC,6EAA6E,CAAC,CAAC;IAC9F,MAAM,IAAI,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IAC1F,MAAM,IAAI,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACzE,MAAM,IAAI,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;AACvE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takaro/db",
|
|
3
|
-
"version": "0.4.10",
|
|
4
3
|
"description": "An opinionated data layer",
|
|
4
|
+
"version": "0.4.11",
|
|
5
|
+
"author": "",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"class-validator": "0.14.2",
|
|
8
|
+
"knex": "3.1.0",
|
|
9
|
+
"ms": "2.1.3",
|
|
10
|
+
"objection": "3.1.5",
|
|
11
|
+
"redis": "4.7.0"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"license": "ISC",
|
|
5
15
|
"main": "dist/main.js",
|
|
6
|
-
"
|
|
7
|
-
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@takaro/config": "*",
|
|
18
|
+
"@takaro/util": "*"
|
|
19
|
+
},
|
|
8
20
|
"scripts": {
|
|
9
|
-
"start:dev": "tsc --watch --preserveWatchOutput -p ./tsconfig.build.json",
|
|
10
21
|
"build": "tsc -p ./tsconfig.build.json",
|
|
11
|
-
"migrate:create": "run(){ touch ./src/migrations/sql/$(date -u +\"%Y%m%d%H%M%S\")-$1.ts; }; run"
|
|
22
|
+
"migrate:create": "run(){ touch ./src/migrations/sql/$(date -u +\"%Y%m%d%H%M%S\")-$1.ts; }; run",
|
|
23
|
+
"start:dev": ":"
|
|
12
24
|
},
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"license": "ISC"
|
|
25
|
+
"type": "module",
|
|
26
|
+
"types": "dist/main.d.ts"
|
|
16
27
|
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
// Create playerInventoryBaseline table - full inventory snapshots every hour
|
|
5
|
+
await knex.raw(`
|
|
6
|
+
CREATE TABLE "playerInventoryBaseline" (
|
|
7
|
+
id UUID DEFAULT gen_random_uuid() NOT NULL,
|
|
8
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
9
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
10
|
+
domain VARCHAR(255) NOT NULL,
|
|
11
|
+
"playerId" UUID NOT NULL,
|
|
12
|
+
"baselineId" UUID NOT NULL,
|
|
13
|
+
"itemId" UUID NOT NULL,
|
|
14
|
+
quantity INTEGER NOT NULL,
|
|
15
|
+
quality VARCHAR(255),
|
|
16
|
+
CONSTRAINT "playerInventoryBaseline_pkey" PRIMARY KEY ("createdAt", "baselineId", "itemId"),
|
|
17
|
+
CONSTRAINT "playerInventoryBaseline_domain_foreign" FOREIGN KEY (domain) REFERENCES domains(id) ON DELETE CASCADE,
|
|
18
|
+
CONSTRAINT "playerInventoryBaseline_playerId_foreign" FOREIGN KEY ("playerId") REFERENCES "playerOnGameServer"(id) ON DELETE CASCADE,
|
|
19
|
+
CONSTRAINT "playerInventoryBaseline_itemId_foreign" FOREIGN KEY ("itemId") REFERENCES items(id) ON DELETE CASCADE,
|
|
20
|
+
CONSTRAINT "playerInventoryBaseline_quantity_check" CHECK (quantity >= 0)
|
|
21
|
+
) PARTITION BY RANGE ("createdAt")
|
|
22
|
+
`);
|
|
23
|
+
|
|
24
|
+
// Create playerInventoryDiff table - individual item changes between baselines
|
|
25
|
+
await knex.raw(`
|
|
26
|
+
CREATE TABLE "playerInventoryDiff" (
|
|
27
|
+
id UUID DEFAULT gen_random_uuid() NOT NULL,
|
|
28
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
29
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
30
|
+
domain VARCHAR(255) NOT NULL,
|
|
31
|
+
"playerId" UUID NOT NULL,
|
|
32
|
+
"itemId" UUID NOT NULL,
|
|
33
|
+
"changeType" VARCHAR(10) NOT NULL,
|
|
34
|
+
"previousQuantity" INTEGER,
|
|
35
|
+
"newQuantity" INTEGER,
|
|
36
|
+
"previousQuality" VARCHAR(255),
|
|
37
|
+
"newQuality" VARCHAR(255),
|
|
38
|
+
CONSTRAINT "playerInventoryDiff_pkey" PRIMARY KEY ("createdAt", "playerId", "itemId"),
|
|
39
|
+
CONSTRAINT "playerInventoryDiff_domain_foreign" FOREIGN KEY (domain) REFERENCES domains(id) ON DELETE CASCADE,
|
|
40
|
+
CONSTRAINT "playerInventoryDiff_playerId_foreign" FOREIGN KEY ("playerId") REFERENCES "playerOnGameServer"(id) ON DELETE CASCADE,
|
|
41
|
+
CONSTRAINT "playerInventoryDiff_itemId_foreign" FOREIGN KEY ("itemId") REFERENCES items(id) ON DELETE CASCADE,
|
|
42
|
+
CONSTRAINT "playerInventoryDiff_changeType_check" CHECK ("changeType" IN ('added', 'removed', 'changed'))
|
|
43
|
+
) PARTITION BY RANGE ("createdAt")
|
|
44
|
+
`);
|
|
45
|
+
|
|
46
|
+
// Create partition function for playerInventoryBaseline
|
|
47
|
+
await knex.raw(`
|
|
48
|
+
CREATE OR REPLACE FUNCTION ensure_player_inventory_baseline_partition(date_param VARCHAR DEFAULT NULL)
|
|
49
|
+
RETURNS VOID AS $$
|
|
50
|
+
DECLARE
|
|
51
|
+
current_day_start DATE;
|
|
52
|
+
next_day_start DATE;
|
|
53
|
+
partition_name TEXT;
|
|
54
|
+
partition_exists BOOLEAN;
|
|
55
|
+
target_date DATE;
|
|
56
|
+
BEGIN
|
|
57
|
+
IF date_param IS NOT NULL THEN
|
|
58
|
+
target_date := DATE(date_param::TIMESTAMP);
|
|
59
|
+
ELSE
|
|
60
|
+
target_date := CURRENT_DATE;
|
|
61
|
+
END IF;
|
|
62
|
+
|
|
63
|
+
current_day_start := DATE_TRUNC('day', target_date);
|
|
64
|
+
next_day_start := current_day_start + INTERVAL '1 day';
|
|
65
|
+
|
|
66
|
+
partition_name := 'playerInventoryBaseline_' || TO_CHAR(current_day_start, 'YYYY_MM_DD');
|
|
67
|
+
|
|
68
|
+
SELECT EXISTS (
|
|
69
|
+
SELECT 1 FROM pg_class c
|
|
70
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
71
|
+
WHERE c.relname = partition_name
|
|
72
|
+
AND n.nspname = 'public'
|
|
73
|
+
) INTO partition_exists;
|
|
74
|
+
|
|
75
|
+
IF NOT partition_exists THEN
|
|
76
|
+
EXECUTE format(
|
|
77
|
+
'CREATE TABLE %I PARTITION OF "playerInventoryBaseline"
|
|
78
|
+
FOR VALUES FROM (%L) TO (%L)',
|
|
79
|
+
partition_name,
|
|
80
|
+
current_day_start,
|
|
81
|
+
next_day_start
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
RAISE NOTICE 'Created partition: % for date: %',
|
|
85
|
+
partition_name, current_day_start;
|
|
86
|
+
END IF;
|
|
87
|
+
END;
|
|
88
|
+
$$ LANGUAGE plpgsql;
|
|
89
|
+
`);
|
|
90
|
+
|
|
91
|
+
// Create partition function for playerInventoryDiff
|
|
92
|
+
await knex.raw(`
|
|
93
|
+
CREATE OR REPLACE FUNCTION ensure_player_inventory_diff_partition(date_param VARCHAR DEFAULT NULL)
|
|
94
|
+
RETURNS VOID AS $$
|
|
95
|
+
DECLARE
|
|
96
|
+
current_day_start DATE;
|
|
97
|
+
next_day_start DATE;
|
|
98
|
+
partition_name TEXT;
|
|
99
|
+
partition_exists BOOLEAN;
|
|
100
|
+
target_date DATE;
|
|
101
|
+
BEGIN
|
|
102
|
+
IF date_param IS NOT NULL THEN
|
|
103
|
+
target_date := DATE(date_param::TIMESTAMP);
|
|
104
|
+
ELSE
|
|
105
|
+
target_date := CURRENT_DATE;
|
|
106
|
+
END IF;
|
|
107
|
+
|
|
108
|
+
current_day_start := DATE_TRUNC('day', target_date);
|
|
109
|
+
next_day_start := current_day_start + INTERVAL '1 day';
|
|
110
|
+
|
|
111
|
+
partition_name := 'playerInventoryDiff_' || TO_CHAR(current_day_start, 'YYYY_MM_DD');
|
|
112
|
+
|
|
113
|
+
SELECT EXISTS (
|
|
114
|
+
SELECT 1 FROM pg_class c
|
|
115
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
116
|
+
WHERE c.relname = partition_name
|
|
117
|
+
AND n.nspname = 'public'
|
|
118
|
+
) INTO partition_exists;
|
|
119
|
+
|
|
120
|
+
IF NOT partition_exists THEN
|
|
121
|
+
EXECUTE format(
|
|
122
|
+
'CREATE TABLE %I PARTITION OF "playerInventoryDiff"
|
|
123
|
+
FOR VALUES FROM (%L) TO (%L)',
|
|
124
|
+
partition_name,
|
|
125
|
+
current_day_start,
|
|
126
|
+
next_day_start
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
RAISE NOTICE 'Created partition: % for date: %',
|
|
130
|
+
partition_name, current_day_start;
|
|
131
|
+
END IF;
|
|
132
|
+
END;
|
|
133
|
+
$$ LANGUAGE plpgsql;
|
|
134
|
+
`);
|
|
135
|
+
|
|
136
|
+
// Create indexes for playerInventoryBaseline
|
|
137
|
+
await knex.raw(
|
|
138
|
+
`CREATE INDEX "playerInventoryBaseline_domain_createdAt_idx" ON "playerInventoryBaseline" (domain, "createdAt")`,
|
|
139
|
+
);
|
|
140
|
+
await knex.raw(`CREATE INDEX "playerInventoryBaseline_playerId_idx" ON "playerInventoryBaseline" ("playerId")`);
|
|
141
|
+
await knex.raw(
|
|
142
|
+
`CREATE INDEX "playerInventoryBaseline_playerId_createdAt_idx" ON "playerInventoryBaseline" ("playerId", "createdAt" DESC)`,
|
|
143
|
+
);
|
|
144
|
+
await knex.raw(`CREATE INDEX "playerInventoryBaseline_baselineId_idx" ON "playerInventoryBaseline" ("baselineId")`);
|
|
145
|
+
|
|
146
|
+
// Create indexes for playerInventoryDiff
|
|
147
|
+
await knex.raw(
|
|
148
|
+
`CREATE INDEX "playerInventoryDiff_domain_createdAt_idx" ON "playerInventoryDiff" (domain, "createdAt")`,
|
|
149
|
+
);
|
|
150
|
+
await knex.raw(`CREATE INDEX "playerInventoryDiff_playerId_idx" ON "playerInventoryDiff" ("playerId")`);
|
|
151
|
+
await knex.raw(
|
|
152
|
+
`CREATE INDEX "playerInventoryDiff_playerId_createdAt_idx" ON "playerInventoryDiff" ("playerId", "createdAt" DESC)`,
|
|
153
|
+
);
|
|
154
|
+
await knex.raw(
|
|
155
|
+
`CREATE INDEX "playerInventoryDiff_itemId_createdAt_idx" ON "playerInventoryDiff" ("itemId", "createdAt" DESC)`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function down(knex: Knex): Promise<void> {
|
|
160
|
+
await knex.raw('DROP FUNCTION IF EXISTS ensure_player_inventory_baseline_partition(VARCHAR)');
|
|
161
|
+
await knex.raw('DROP FUNCTION IF EXISTS ensure_player_inventory_diff_partition(VARCHAR)');
|
|
162
|
+
await knex.raw('DROP TABLE IF EXISTS "playerInventoryBaseline" CASCADE');
|
|
163
|
+
await knex.raw('DROP TABLE IF EXISTS "playerInventoryDiff" CASCADE');
|
|
164
|
+
}
|
package/tsconfig.build.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "./tsconfig.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
+
"composite": true,
|
|
4
5
|
"rootDir": "./src",
|
|
5
6
|
"outDir": "dist"
|
|
6
7
|
},
|
|
7
8
|
"include": ["src/**/*"],
|
|
8
|
-
"exclude": ["src/**/*.test.ts"]
|
|
9
|
+
"exclude": ["src/**/*.test.ts"],
|
|
10
|
+
"references": [
|
|
11
|
+
{ "path": "../lib-config/tsconfig.build.json" },
|
|
12
|
+
{ "path": "../lib-util/tsconfig.build.json" }
|
|
13
|
+
]
|
|
9
14
|
}
|