-
Notifications
You must be signed in to change notification settings - Fork 4
Use @fastify/fastify-postgres. CheckerNetwork/roadmap#220 #341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
31a5f9b
6206573
51bfcad
3717210
973b0da
826d075
e89a63c
26d73c7
2608fdc
c0a95b2
6a76461
f6a0319
59448e4
9423683
97ac2bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -21,28 +21,27 @@ export const addPlatformRoutes = (app) => { | |||||
app.addHook('onSend', filterOnSendHook) | ||||||
|
||||||
app.get('/stations/daily', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchDailyStationCount(request.server.pg.evaluate, request.filter)) | ||||||
}) | ||||||
app.get('/stations/monthly', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchMonthlyStationCount(request.server.pg.evaluate, request.filter)) | ||||||
reply.send(await fetchMonthlyStationCount(request.server.pg, request.filter)) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
We could also pass correct instance of the database instead of passing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This throws an error reason why went with only the pg object, besides the fetcher functions expects full pg object and uses pg.stats or pg.evaluate interally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What error does it throw? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping @Goddhi |
||||||
}) | ||||||
app.get('/stations/desktop/daily', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchDailyDesktopUsers(request.server.pg.stats, request.filter)) | ||||||
reply.send(await fetchDailyDesktopUsers(request.server.pg, request.filter)) | ||||||
}) | ||||||
app.get('/measurements/daily', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchDailyStationMeasurementCounts(request.server.pg.evaluate, request.filter)) | ||||||
reply.send(await fetchDailyStationMeasurementCounts(request.server.pg, request.filter)) | ||||||
}) | ||||||
app.get('/participants/top-measurements', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchParticipantsWithTopMeasurements(request.server.pg.evaluate, request.filter)) | ||||||
reply.send(await fetchParticipantsWithTopMeasurements(request.server.pg, request.filter)) | ||||||
}) | ||||||
app.get('/participants/top-earning', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchTopEarningParticipants(request.server.pg.stats, request.filter)) }) | ||||||
reply.send(await fetchTopEarningParticipants(request.server.pg, request.filter)) }) | ||||||
|
||||||
app.get('/participants/accumulative/daily', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchAccumulativeDailyParticipantCount(request.server.pg.evaluate, request.filter)) | ||||||
reply.send(await fetchAccumulativeDailyParticipantCount(request.server.pg, request.filter)) | ||||||
}) | ||||||
app.get('/transfers/daily', async (/** @type {RequestWithFilter} */ request, reply) => { | ||||||
reply.send(await fetchDailyRewardTransfers(request.server.pg.stats, request.filter)) | ||||||
reply.send(await fetchDailyRewardTransfers(request.server.pg, request.filter)) | ||||||
}) | ||||||
}) | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,16 +1,24 @@ | ||||||||||
import assert from 'http-assert' | ||||||||||
import { today, yesterday } from './request-helpers.js' | ||||||||||
|
||||||||||
/** @typedef {import('./typings.js').DateRangeFilter} DateRangeFilter */ | ||||||||||
/** | ||||||||||
@typedef {import('./typings.js').DateRangeFilter} DateRangeFilter | ||||||||||
@typedef {import('@filecoin-station/spark-stats-db').Queryable} Queryable | ||||||||||
@typedef {import('./typings.js').FastifyPg} FastifyPg | ||||||||||
*/ | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {FastifyPg} pg - Fastify pg object with database connections | ||||||||||
*/ | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping @Goddhi |
||||||||||
|
||||||||||
const ONE_DAY = 24 * 60 * 60 * 1000 | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchDailyStationCount = async (pg, filter) => { | ||||||||||
|
||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.evaluate.query(` | ||||||||||
SELECT day::TEXT, station_count | ||||||||||
FROM daily_platform_stats | ||||||||||
WHERE day >= $1 AND day <= $2 | ||||||||||
|
@@ -20,11 +28,11 @@ export const fetchDailyStationCount = async (pg, filter) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchMonthlyStationCount = async (pg, filter) => { | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.evaluate.query(` | ||||||||||
SELECT month::TEXT, station_count | ||||||||||
FROM monthly_active_station_count | ||||||||||
WHERE | ||||||||||
|
@@ -36,11 +44,11 @@ export const fetchMonthlyStationCount = async (pg, filter) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchDailyStationMeasurementCounts = async (pg, filter) => { | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.evaluate.query(` | ||||||||||
SELECT day::TEXT, accepted_measurement_count, total_measurement_count | ||||||||||
FROM daily_platform_stats | ||||||||||
WHERE day >= $1 AND day <= $2 | ||||||||||
|
@@ -50,22 +58,22 @@ export const fetchDailyStationMeasurementCounts = async (pg, filter) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchParticipantsWithTopMeasurements = async (pg, filter) => { | ||||||||||
assert(filter.to === filter.from, 400, 'Multi-day queries are not supported for this endpoint') | ||||||||||
assert(filter.to === yesterday(), 400, 'filter.to must be set to yesterday, other values are not supported yet') | ||||||||||
// Ignore the filter for this query | ||||||||||
// Get the top measurement stations from the Materialized View | ||||||||||
return (await pg.query(` | ||||||||||
return (await pg.evaluate.query(` | ||||||||||
SELECT day::TEXT, participant_address, station_count, accepted_measurement_count, inet_group_count | ||||||||||
FROM top_measurement_participants_yesterday_mv | ||||||||||
`)).rows | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchDailyRewardTransfers = async (pg, filter) => { | ||||||||||
|
@@ -74,7 +82,7 @@ export const fetchDailyRewardTransfers = async (pg, filter) => { | |||||||||
400, | ||||||||||
'Date range must be 31 days max' | ||||||||||
) | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.stats.query(` | ||||||||||
SELECT day::TEXT, to_address, amount | ||||||||||
FROM daily_reward_transfers | ||||||||||
WHERE day >= $1 AND day <= $2 | ||||||||||
|
@@ -99,11 +107,11 @@ export const fetchDailyRewardTransfers = async (pg, filter) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchAccumulativeDailyParticipantCount = async (pg, filter) => { | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.evaluate.query(` | ||||||||||
WITH first_appearance AS ( | ||||||||||
SELECT participant_id, MIN(day) as day | ||||||||||
FROM daily_participants | ||||||||||
|
@@ -126,15 +134,15 @@ export const fetchAccumulativeDailyParticipantCount = async (pg, filter) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchTopEarningParticipants = async (pg, filter) => { | ||||||||||
// The query combines "transfers until filter.to" with "latest scheduled rewards as of today". | ||||||||||
// As a result, it produces incorrect result if `to` is different from `now()`. | ||||||||||
// See https://github.com/filecoin-station/spark-stats/pull/170#discussion_r1664080395 | ||||||||||
assert(filter.to === today(), 400, 'filter.to must be today, other values are not supported') | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.stats.query(` | ||||||||||
WITH latest_scheduled_rewards AS ( | ||||||||||
SELECT DISTINCT ON (participant_address) participant_address, scheduled_rewards | ||||||||||
FROM daily_scheduled_rewards | ||||||||||
|
@@ -154,10 +162,10 @@ export const fetchTopEarningParticipants = async (pg, filter) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
*/ | ||||||||||
* @param {FastifyPg} pg | ||||||||||
*/ | ||||||||||
export const fetchParticipantsSummary = async (pg) => { | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.evaluate.query(` | ||||||||||
SELECT COUNT(DISTINCT participant_id) FROM daily_participants | ||||||||||
`) | ||||||||||
return { | ||||||||||
|
@@ -166,11 +174,11 @@ export const fetchParticipantsSummary = async (pg) => { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @param {Object} pg | ||||||||||
* @param {FastifyPg} pg | ||||||||||
* @param {import('./typings.js').DateRangeFilter} filter | ||||||||||
*/ | ||||||||||
export const fetchDailyDesktopUsers = async (pg, filter) => { | ||||||||||
const { rows } = await pg.query(` | ||||||||||
const { rows } = await pg.stats.query(` | ||||||||||
SELECT | ||||||||||
day::TEXT, | ||||||||||
user_count | ||||||||||
|
@@ -180,4 +188,4 @@ export const fetchDailyDesktopUsers = async (pg, filter) => { | |||||||||
[filter.from, filter.to]) | ||||||||||
|
||||||||||
return rows | ||||||||||
} | ||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,7 +1,13 @@ | ||||||
/** | ||||||
@typedef {import('@filecoin-station/spark-stats-db').Queryable} Queryable | ||||||
@typedef {import('./typings.js').FastifyPg} FastifyPg | ||||||
*/ | ||||||
|
||||||
/** | ||||||
* @param {Object} pg - Fastify pg object with database connections | ||||||
* @param {import('./typings.js').DateRangeFilter & {nonZero?: 'true'}} filter | ||||||
* @param {FastifyPg} pg - Fastify pg object with database connections | ||||||
*/ | ||||||
|
||||||
export const fetchRetrievalSuccessRate = async (pg, filter) => { | ||||||
// Fetch the "day" (DATE) as a string (TEXT) to prevent node-postgres for converting it into | ||||||
// a JavaScript Date with a timezone, as that could change the date one day forward or back. | ||||||
|
@@ -35,7 +41,7 @@ export const fetchRetrievalSuccessRate = async (pg, filter) => { | |||||
} | ||||||
|
||||||
/** | ||||||
* @param {Object} pg | ||||||
* @param {any} pg - Fastify pg object with database connections | ||||||
|
* @param {any} pg - Fastify pg object with database connections | |
* @param {FastifyPg} pg - Fastify pg object with database connections |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @Goddhi
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this not also be FastifyPg
?
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,16 @@ | ||
import { FastifyRequest } from 'fastify' | ||
import { PostgresDb } from '@fastify/postgres' | ||
import { Queryable } from '@filecoin-station/spark-stats-db' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is this type imported for? |
||
|
||
|
||
export type FastifyPg = PostgresDb & Record<string, PostgresDb> | ||
|
||
export interface DateRangeFilter { | ||
from: string; | ||
to: string; | ||
} | ||
|
||
|
||
export type RequestWithFilter = FastifyRequest<{ | ||
Querystring: { from: string, to: string } | ||
}> | ||
|
Uh oh!
There was an error while loading. Please reload this page.