Refactor trending tags history, make it more correct

This commit is contained in:
Alex Gleason 2023-07-26 17:18:21 -05:00
parent f8d46cae58
commit bc3a96eeed
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
4 changed files with 60 additions and 29 deletions

View File

@ -3,6 +3,7 @@ import { Conf } from '@/config.ts';
import { z } from '@/deps.ts'; import { z } from '@/deps.ts';
import { trends } from '@/trends.ts'; import { trends } from '@/trends.ts';
import { Time } from '@/utils.ts'; import { Time } from '@/utils.ts';
import { stripTime } from '@/utils/time.ts';
const limitSchema = z.coerce.number().catch(10).transform((value) => Math.min(Math.max(value, 0), 20)); const limitSchema = z.coerce.number().catch(10).transform((value) => Math.min(Math.max(value, 0), 20));
@ -25,11 +26,11 @@ const trendingTagsController: AppController = (c) => {
url: Conf.local(`/tags/${name}`), url: Conf.local(`/tags/${name}`),
history: [ history: [
{ {
day: String(Math.floor(now.getTime() / 1000)), day: String(Math.floor(stripTime(now).getTime() / 1000)),
accounts: String(accounts), accounts: String(accounts),
uses: String(uses), uses: String(uses),
}, },
...getTagHistoryWithGapsFilled({ ...trends.getTagHistory({
tag: name, tag: name,
since: lastWeek, since: lastWeek,
until: now, until: now,
@ -44,28 +45,4 @@ const trendingTagsController: AppController = (c) => {
}))); })));
}; };
function generateDateRange(since: Date, until: Date): Date[] {
const dates = [];
const sinceDate = new Date(Date.UTC(since.getUTCFullYear(), since.getUTCMonth(), since.getUTCDate() + 1));
const untilDate = new Date(Date.UTC(until.getUTCFullYear(), until.getUTCMonth(), until.getUTCDate()));
while (sinceDate < untilDate) {
dates.push(new Date(sinceDate));
sinceDate.setUTCDate(sinceDate.getUTCDate() + 1);
}
return dates.reverse();
}
function getTagHistoryWithGapsFilled(params: Parameters<typeof trends.getTagHistory>[0]) {
const history = trends.getTagHistory(params);
const dateRange = generateDateRange(params.since, params.until);
return dateRange.map((day) => {
const data = history.find((item) => item.day.getTime() === day.getTime());
return data || { day, accounts: 0, uses: 0 };
});
}
export { trendingTagsController }; export { trendingTagsController };

View File

@ -1,6 +1,7 @@
import { Sqlite } from '@/deps.ts'; import { Sqlite } from '@/deps.ts';
import { hashtagSchema, hexIdSchema } from '@/schema.ts'; import { hashtagSchema, hexIdSchema } from '@/schema.ts';
import { Time } from './utils.ts'; import { Time } from '@/utils.ts';
import { generateDateRange } from '@/utils/time.ts';
interface GetTrendingTagsOpts { interface GetTrendingTagsOpts {
since: Date; since: Date;
@ -63,7 +64,7 @@ class TrendsDB {
} }
getTagHistory({ tag, since, until, limit = 7, offset = 0 }: GetTagHistoryOpts) { getTagHistory({ tag, since, until, limit = 7, offset = 0 }: GetTagHistoryOpts) {
return this.#db.query<string[]>( const result = this.#db.query<string[]>(
` `
SELECT date(inserted_at), COUNT(DISTINCT pubkey8), COUNT(*) SELECT date(inserted_at), COUNT(DISTINCT pubkey8), COUNT(*)
FROM tag_usages FROM tag_usages
@ -79,6 +80,16 @@ class TrendsDB {
accounts: Number(row[1]), accounts: Number(row[1]),
uses: Number(row[2]), uses: Number(row[2]),
})); }));
const dateRange = generateDateRange(
new Date(since.getTime() + Time.days(1)),
new Date(until.getTime() - Time.days(offset)),
).reverse();
return dateRange.map((day) => {
const data = result.find((item) => item.day.getTime() === day.getTime());
return data || { day, accounts: 0, uses: 0 };
});
} }
addTagUsages(pubkey: string, hashtags: string[], date = new Date()): void { addTagUsages(pubkey: string, hashtags: string[], date = new Date()): void {

23
src/utils/time.test.ts Normal file
View File

@ -0,0 +1,23 @@
import { assertEquals } from '@/deps-test.ts';
import { generateDateRange } from './time.ts';
Deno.test('generateDateRange', () => {
const since = new Date('2023-07-03T16:30:00.000Z');
const until = new Date('2023-07-07T09:01:00.000Z');
const expected = [
new Date('2023-07-03T00:00:00.000Z'),
new Date('2023-07-04T00:00:00.000Z'),
new Date('2023-07-05T00:00:00.000Z'),
new Date('2023-07-06T00:00:00.000Z'),
new Date('2023-07-07T00:00:00.000Z'),
];
const result = generateDateRange(since, until);
assertEquals(
result.map((d) => d.getTime()),
expected.map((d) => d.getTime()),
);
});

View File

@ -9,4 +9,24 @@ const Time = {
years: (y: number) => y * Time.days(365), years: (y: number) => y * Time.days(365),
}; };
export { Time }; /** Strips the time off the date, giving 12am UTC. */
function stripTime(date: Date): Date {
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
}
/** Strips times off the dates and generates all 24h intervals between them, inclusive of both inputs. */
function generateDateRange(since: Date, until: Date): Date[] {
const dates = [];
const sinceDate = stripTime(since);
const untilDate = stripTime(until);
while (sinceDate <= untilDate) {
dates.push(new Date(sinceDate));
sinceDate.setUTCDate(sinceDate.getUTCDate() + 1);
}
return dates;
}
export { generateDateRange, stripTime, Time };