Skip to content
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

feat: GET /deals/summary #161

Merged
merged 5 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ Base URL: http://stats.filspark.com/

http://stats.filspark.com/deals/daily

- `GET /deals/summary?from=2024-01-01&to=2024-01-31`

http://stats.filspark.com/deals/summary


## Development

### Database
Expand Down
5 changes: 4 additions & 1 deletion stats/lib/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
fetchParticipantChangeRates,
fetchParticipantScheduledRewards,
fetchParticipantRewardTransfers,
fetchRetrievalSuccessRate
fetchRetrievalSuccessRate,
fetchDealSummary
} from './stats-fetchers.js'

import { handlePlatformRoutes } from './platform-routes.js'
Expand Down Expand Up @@ -83,6 +84,8 @@ const handler = async (req, res, pgPools) => {

if (req.method === 'GET' && url === '/deals/daily') {
await respond(fetchDailyDealStats)
} else if (req.method === 'GET' && url === '/deals/summary') {
await respond(fetchDealSummary)
} else if (req.method === 'GET' && url === '/retrieval-success-rate') {
await respond(fetchRetrievalSuccessRate)
} else if (req.method === 'GET' && url === '/participants/daily') {
Expand Down
18 changes: 18 additions & 0 deletions stats/lib/stats-fetchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ export const fetchDailyDealStats = async (pgPools, filter) => {
return rows
}

/**
* @param {import('@filecoin-station/spark-stats-db').PgPools} pgPools
* @param {import('./typings.js').DateRangeFilter} filter
*/
export const fetchDealSummary = async (pgPools, filter) => {
const { rows: [summary] } = await pgPools.evaluate.query(`
SELECT
SUM(total) as total,
SUM(indexed) as indexed,
SUM(retrievable) as retrievable
FROM daily_deals
WHERE day >= date_trunc('day', $1::DATE)
AND day <= date_trunc('day', $2::DATE)
`, [filter.from, filter.to]
)
return summary
}

export const fetchDailyParticipants = async (pgPools, filter) => {
return await getDailyDistinctCount({
pgPool: pgPools.evaluate,
Expand Down
51 changes: 51 additions & 0 deletions stats/test/handler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,57 @@ describe('HTTP request handler', () => {
})
})

describe('GET /deals/summary', () => {
it('returns deal summary for the given date range (including the end day)', async () => {
await givenDailyDealStats(pgPools.evaluate, { day: '2024-03-12', total: 200, indexed: 52, retrievable: 2 })
// filter.to - 7 days -> should be excluded
await givenDailyDealStats(pgPools.evaluate, { day: '2024-03-23', total: 300, indexed: 53, retrievable: 3 })
// last 7 days
await givenDailyDealStats(pgPools.evaluate, { day: '2024-03-24', total: 400, indexed: 54, retrievable: 4 })
await givenDailyDealStats(pgPools.evaluate, { day: '2024-03-29', total: 500, indexed: 55, retrievable: 5 })
// `filter.to` (e.g. today) - should be included
await givenDailyDealStats(pgPools.evaluate, { day: '2024-03-30', total: 6000, indexed: 600, retrievable: 60 })
// after the requested range
await givenDailyDealStats(pgPools.evaluate, { day: '2024-03-31', total: 70000, indexed: 7000, retrievable: 700 })

const res = await fetch(
new URL(
'/deals/summary?from=2024-03-24&to=2024-03-30',
baseUrl
), {
redirect: 'manual'
}
)
await assertResponseStatus(res, 200)
const stats = await res.json()

assert.deepStrictEqual(stats, {
total: '6900',
indexed: '709',
retrievable: '69'
})
})

it('handles query for future date with no recorded stats', async () => {
const res = await fetch(
new URL(
'/deals/summary?from=3024-04-24&to=3024-03-30',
baseUrl
), {
redirect: 'manual'
}
)
await assertResponseStatus(res, 200)
const stats = await res.json()

assert.deepStrictEqual(stats, {
total: null,
indexed: null,
retrievable: null
})
})
})

describe('CORS', () => {
it('sets CORS headers for requests from Station Desktop in production', async () => {
const res = await fetch(new URL('/', baseUrl), {
Expand Down