-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmerge.js
117 lines (99 loc) · 2.94 KB
/
merge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import {
S3Client,
PutObjectCommand,
DeleteObjectsCommand,
ListObjectsV2Command,
} from "@aws-sdk/client-s3";
import {
CloudFrontClient,
CreateInvalidationCommand,
} from "@aws-sdk/client-cloudfront";
// import { fromIni } from "@aws-sdk/credential-providers";
import { csvFormat, csvParse } from "d3-dsv";
import { group } from "d3-array";
import fetch from "node-fetch";
import { eachLimit } from "async";
export const handler = async () => {
let puts = 0;
const bucket = "stash.michigandaily.com";
const winter = "course-tracker/winter-2023";
const region = "us-east-2";
const client = new S3Client({
region,
// credentials: fromIni({ profile: "sink" }),
});
const cloudfront = new CloudFrontClient({ region });
const lister = new ListObjectsV2Command({ Bucket: bucket, Prefix: `${winter}/stubs/stub-` });
const list = await client.send(lister);
if (list.KeyCount === 0) {
console.log("No stubs to merge");
return;
}
const stubs = list.Contents.map(d => ({ Key: d.Key }));
for await (const { Key } of stubs) {
const stubRes = await fetch(`https://${bucket}/${Key}`);
const stubText = await stubRes.text();
const stub = csvParse(stubText);
const stubByCourse = group(stub, d => d.Course);
const NUM_OPERATIONS = 25;
await eachLimit(stubByCourse.entries(), NUM_OPERATIONS, async ([k, v]) => {
const department = k.slice(0, -3).toLowerCase();
const number = +k.slice(-3);
const s = v.map(({ Course, ...attributes }) => attributes)
let csv;
let mainRes;
try {
mainRes = await fetch(`https://${bucket}/${winter}/courses/${department}/${department}-${number}.csv`);
} catch (e) {
return;
}
if (mainRes.ok) {
const mainText = await mainRes.text();
const main = csvParse(mainText);
if (Date.parse(main.at(-1).Time) >= Date.parse(s.at(0).Time)) {
return;
} else {
csv = [...main, ...s];
}
} else {
if (mainRes.status === 404) {
csv = s;
} else {
return;
}
}
await client.send(
new PutObjectCommand({
Bucket: bucket,
Key: `${winter}/courses/${department}/${department}-${number}.csv`,
Body: csvFormat(csv),
ContentType: "text/csv",
CacheControl: "s-maxage=3500"
})
);
puts++;
})
const invalidate = new CreateInvalidationCommand({
DistributionId: "E1FI50AV220BXR",
InvalidationBatch: {
CallerReference: new Date().toISOString(),
Paths: {
Quantity: 1,
Items: ["/" + winter + "/*"],
},
},
});
await cloudfront.send(invalidate);
}
if (stubs.length > 0) {
const remover = new DeleteObjectsCommand({
Bucket: bucket,
Delete: {
Objects: stubs,
}
});
await client.send(remover);
}
console.log("PUT:", puts, "merges");
};
handler();