Skip to content

Commit

Permalink
Move more queries to API
Browse files Browse the repository at this point in the history
  • Loading branch information
wilsonzlin committed May 4, 2024
1 parent 414fc31 commit 749a704
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 0 deletions.
52 changes: 52 additions & 0 deletions api/endpoint/analyzePopularity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
VFiniteNumber,
VHumanString,
VInteger,
VStruct,
Valid,
} from "@wzlin/valid";
import assertInstanceOf from "@xtjs/lib/assertInstanceOf";
import { QueryGroupByOutput, makeQuery } from "../query";

const input = new VStruct({
query: new VHumanString(1, 512),
simMinHundredths: new VInteger(80, 100),
});

export const endpointAnalyzePopularity = {
input,
handler: async ({ query, simMinHundredths }: Valid<typeof input>) => {
const simThreshold = simMinHundredths / 100;
const res = await makeQuery({
dataset: "post",
queries: [query],
scales: {
sim: { min: simThreshold, max: 1.0 },
},
post_filter_clip: {
sim: { min: simThreshold, max: 1.0 },
// Some posts have UNIX timestamp 0.
ts_day: { min: 1, max: Number.MAX_SAFE_INTEGER },
},
weights: {
votes: "sim",
},
outputs: [
{
group_by: {
by: "ts_day",
bucket: 7,
cols: [["final_score", "sum"]],
},
},
],
});
const data = assertInstanceOf(res[0], QueryGroupByOutput);
return {
timestamps: [...data.groups(new VInteger())].map(
(d) => new Date(d * 7 * 24 * 60 * 60 * 1000),
),
scores: [...data.column("final_score", new VFiniteNumber())],
};
},
};
46 changes: 46 additions & 0 deletions api/endpoint/topPosts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
VFiniteNumber,
VHumanString,
VInteger,
VStruct,
Valid,
} from "@wzlin/valid";
import assertInstanceOf from "@xtjs/lib/assertInstanceOf";
import { QueryItemsOutput, makeQuery } from "../query";

const input = new VStruct({
query: new VHumanString(1, 512),
limit: new VInteger(1, 20),
simMinHundredths: new VInteger(80, 100),
});

export const endpointTopPosts = {
input,
handler: async ({ query, limit, simMinHundredths }: Valid<typeof input>) => {
const simThreshold = simMinHundredths / 100;
const res = await makeQuery({
dataset: "post",
queries: [query],
post_filter_clip: {
sim: { min: simThreshold, max: 1 },
},
outputs: [
{
items: {
cols: ["id", "sim"],
limit,
order_asc: false,
order_by: "votes",
},
},
],
});
const data = assertInstanceOf(res[0], QueryItemsOutput);
return [
...data.items({
id: new VInteger(1),
sim: new VFiniteNumber(),
}),
];
},
};
57 changes: 57 additions & 0 deletions api/endpoint/topUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
VFiniteNumber,
VHumanString,
VInteger,
VString,
VStruct,
Valid,
} from "@wzlin/valid";
import assertInstanceOf from "@xtjs/lib/assertInstanceOf";
import { QueryGroupByOutput, makeQuery } from "../query";

const input = new VStruct({
query: new VHumanString(1, 512),
limit: new VInteger(1, 20),
simMinHundredths: new VInteger(80, 100),
});

export const endpointTopUsers = {
input,
handler: async ({ query, limit, simMinHundredths }: Valid<typeof input>) => {
const simThreshold = simMinHundredths / 100;
const res = await makeQuery({
dataset: "comment",
queries: [query],
scales: {
sim: {
min: simThreshold,
max: 1,
},
},
weights: {
// We can't multiply by votes, because the HN API does not expose votes for anything except posts.
sim_scaled: 1,
},
outputs: [
{
group_by: {
by: "user",
cols: [["final_score", "sum"]],
order_by: "final_score",
order_asc: false,
limit,
},
},
],
});
const data = assertInstanceOf(res[0], QueryGroupByOutput);
return [
...data.entries(new VString(), {
final_score: new VFiniteNumber(),
}),
].map((e) => ({
user: e[0],
score: e[1].final_score,
}));
},
};
6 changes: 6 additions & 0 deletions api/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import readBufferStream from "@xtjs/lib/readBufferStream";
import uint8ArrayToBuffer from "@xtjs/lib/uint8ArrayToBuffer";
import { createSecureServer } from "http2";
import { lg } from "../common/res";
import { endpointAnalyzePopularity } from "./endpoint/analyzePopularity";
import { endpointAnalyzeSentiment } from "./endpoint/analyzeSentiment";
import { endpointHeatmap } from "./endpoint/heatmap";
import { endpointSearch } from "./endpoint/search";
import { endpointTopPosts } from "./endpoint/topPosts";
import { endpointTopUsers } from "./endpoint/topUsers";

const getPemEnv = (name: string) =>
uint8ArrayToBuffer(
Expand All @@ -22,9 +25,12 @@ type Endpoint = {
};

const ENDPOINTS: Record<string, Endpoint> = {
analyzePopularity: endpointAnalyzePopularity,
analyzeSentiment: endpointAnalyzeSentiment,
heatmap: endpointHeatmap,
search: endpointSearch,
topPosts: endpointTopPosts,
topUsers: endpointTopUsers,
};

createSecureServer(
Expand Down

0 comments on commit 749a704

Please sign in to comment.