stacker.news/api/resolvers/growth.js

174 lines
7.3 KiB
JavaScript
Raw Normal View History

2022-06-10 19:20:33 +00:00
const PLACEHOLDERS_NUM = 616
2022-12-01 21:31:04 +00:00
function interval (when) {
switch (when) {
case 'week':
return '1 week'
case 'month':
return '1 month'
case 'year':
return '1 year'
case 'forever':
return null
default:
return '1 day'
}
}
function timeUnit (when) {
switch (when) {
case 'week':
case 'month':
return 'day'
case 'year':
case 'forever':
return 'month'
default:
return 'hour'
}
}
function withClause (when) {
const ival = interval(when)
const unit = timeUnit(when)
return `
WITH range_values AS (
SELECT date_trunc('${unit}', ${ival ? "now_utc() - interval '" + ival + "'" : "'2021-06-07'::timestamp"}) as minval,
date_trunc('${unit}', now_utc()) as maxval),
times AS (
SELECT generate_series(minval, maxval, interval '1 ${unit}') as time
FROM range_values
)
`
}
2022-12-01 23:14:16 +00:00
// HACKY AF this is a performance enhancement that allows us to use the created_at indices on tables
function intervalClause (when, table, and) {
if (when === 'forever') {
return and ? '' : 'TRUE'
}
return `"${table}".created_at >= now_utc() - interval '${interval(when)}' ${and ? 'AND' : ''} `
}
2022-06-10 19:20:33 +00:00
export default {
Query: {
2022-12-01 21:31:04 +00:00
registrationGrowth: async (parent, { when }, { models }) => {
2022-06-10 19:20:33 +00:00
return await models.$queryRaw(
2022-12-01 21:31:04 +00:00
`${withClause(when)}
SELECT time, json_build_array(
json_build_object('name', 'invited', 'value', count("inviteId")),
json_build_object('name', 'organic', 'value', count(users.id) FILTER(WHERE id > ${PLACEHOLDERS_NUM}) - count("inviteId"))
) AS data
FROM times
2022-12-01 23:14:16 +00:00
LEFT JOIN users ON ${intervalClause(when, 'users', true)} time = date_trunc('${timeUnit(when)}', created_at)
2022-06-10 19:20:33 +00:00
GROUP BY time
ORDER BY time ASC`)
},
2022-12-01 21:31:04 +00:00
spenderGrowth: async (parent, { when }, { models }) => {
2022-06-10 19:20:33 +00:00
return await models.$queryRaw(
2022-12-01 21:31:04 +00:00
`${withClause(when)}
SELECT time, json_build_array(
2022-12-06 19:26:33 +00:00
json_build_object('name', 'any', 'value', count(DISTINCT "userId")),
json_build_object('name', 'jobs', 'value', count(DISTINCT "userId") FILTER (WHERE act = 'STREAM')),
json_build_object('name', 'boost', 'value', count(DISTINCT "userId") FILTER (WHERE act = 'BOOST')),
json_build_object('name', 'fees', 'value', count(DISTINCT "userId") FILTER (WHERE act = 'FEE')),
2022-12-08 00:04:02 +00:00
json_build_object('name', 'tips', 'value', count(DISTINCT "userId") FILTER (WHERE act = 'TIP')),
json_build_object('name', 'donation', 'value', count(DISTINCT "userId") FILTER (WHERE act = 'DONATION'))
2022-12-01 21:31:04 +00:00
) AS data
FROM times
2022-12-08 00:04:02 +00:00
LEFT JOIN
((SELECT "ItemAct".created_at, "userId", act::text as act
FROM "ItemAct"
WHERE ${intervalClause(when, 'ItemAct', false)})
UNION ALL
(SELECT created_at, "userId", 'DONATION' as act
FROM "Donation"
WHERE ${intervalClause(when, 'Donation', false)})) u ON time = date_trunc('${timeUnit(when)}', u.created_at)
2022-06-10 19:20:33 +00:00
GROUP BY time
ORDER BY time ASC`)
},
2022-12-01 21:31:04 +00:00
itemGrowth: async (parent, { when }, { models }) => {
2022-06-10 19:20:33 +00:00
return await models.$queryRaw(
2022-12-01 21:31:04 +00:00
`${withClause(when)}
SELECT time, json_build_array(
json_build_object('name', 'comments', 'value', count("parentId")),
json_build_object('name', 'jobs', 'value', count("subName")),
json_build_object('name', 'posts', 'value', count("Item".id)-count("parentId")-count("subName"))
) AS data
FROM times
2022-12-01 23:14:16 +00:00
LEFT JOIN "Item" ON ${intervalClause(when, 'Item', true)} time = date_trunc('${timeUnit(when)}', created_at)
2022-06-10 19:20:33 +00:00
GROUP BY time
ORDER BY time ASC`)
},
2022-12-01 21:31:04 +00:00
spendingGrowth: async (parent, { when }, { models }) => {
2022-06-10 19:20:33 +00:00
return await models.$queryRaw(
2022-12-01 21:31:04 +00:00
`${withClause(when)}
SELECT time, json_build_array(
2022-12-08 00:04:02 +00:00
json_build_object('name', 'jobs', 'value', coalesce(floor(sum(CASE WHEN act = 'STREAM' THEN msats ELSE 0 END)/1000),0)),
json_build_object('name', 'boost', 'value', coalesce(floor(sum(CASE WHEN act = 'BOOST' THEN msats ELSE 0 END)/1000),0)),
json_build_object('name', 'fees', 'value', coalesce(floor(sum(CASE WHEN act NOT IN ('BOOST', 'TIP', 'STREAM', 'DONATION') THEN msats ELSE 0 END)/1000),0)),
json_build_object('name', 'tips', 'value', coalesce(floor(sum(CASE WHEN act = 'TIP' THEN msats ELSE 0 END)/1000),0)),
json_build_object('name', 'donations', 'value', coalesce(floor(sum(CASE WHEN act = 'DONATION' THEN msats ELSE 0 END)/1000),0))
2022-12-01 21:31:04 +00:00
) AS data
FROM times
2022-12-08 00:04:02 +00:00
LEFT JOIN
((SELECT "ItemAct".created_at, msats, act::text as act
FROM "ItemAct"
WHERE ${intervalClause(when, 'ItemAct', false)})
UNION ALL
(SELECT created_at, sats * 1000 as msats, 'DONATION' as act
FROM "Donation"
WHERE ${intervalClause(when, 'Donation', false)})) u ON time = date_trunc('${timeUnit(when)}', u.created_at)
2022-06-10 19:20:33 +00:00
GROUP BY time
ORDER BY time ASC`)
2022-06-22 21:13:51 +00:00
},
2022-12-01 21:31:04 +00:00
stackerGrowth: async (parent, { when }, { models }) => {
2022-06-22 21:13:51 +00:00
return await models.$queryRaw(
2022-12-01 21:31:04 +00:00
`${withClause(when)}
SELECT time, json_build_array(
2022-12-06 19:26:33 +00:00
json_build_object('name', 'any', 'value', count(distinct user_id)),
json_build_object('name', 'posts', 'value', count(distinct user_id) FILTER (WHERE type = 'POST')),
json_build_object('name', 'comments', 'value', count(distinct user_id) FILTER (WHERE type = 'COMMENT')),
json_build_object('name', 'rewards', 'value', count(distinct user_id) FILTER (WHERE type = 'EARN'))
2022-12-01 21:31:04 +00:00
) AS data
FROM times
LEFT JOIN
2022-12-06 19:26:33 +00:00
((SELECT "ItemAct".created_at, "Item"."userId" as user_id, CASE WHEN "Item"."parentId" IS NULL THEN 'POST' ELSE 'COMMENT' END as type
2022-06-22 21:13:51 +00:00
FROM "ItemAct"
2022-12-01 21:31:04 +00:00
JOIN "Item" on "ItemAct"."itemId" = "Item".id
2022-12-01 23:14:16 +00:00
WHERE ${intervalClause(when, 'ItemAct', true)} "ItemAct".act = 'TIP')
2022-06-22 21:13:51 +00:00
UNION ALL
2022-12-06 19:26:33 +00:00
(SELECT created_at, "userId" as user_id, 'EARN' as type
2022-12-01 23:14:16 +00:00
FROM "Earn"
WHERE ${intervalClause(when, 'Earn', false)})) u ON time = date_trunc('${timeUnit(when)}', u.created_at)
2022-06-22 21:13:51 +00:00
GROUP BY time
ORDER BY time ASC`)
2022-06-24 15:38:00 +00:00
},
2022-12-01 21:31:04 +00:00
stackingGrowth: async (parent, { when }, { models }) => {
2022-06-24 15:38:00 +00:00
return await models.$queryRaw(
2022-12-01 21:31:04 +00:00
`${withClause(when)}
SELECT time, json_build_array(
json_build_object('name', 'rewards', 'value', coalesce(floor(sum(airdrop)/1000),0)),
json_build_object('name', 'posts', 'value', coalesce(floor(sum(post)/1000),0)),
json_build_object('name', 'comments', 'value', coalesce(floor(sum(comment)/1000),0))
) AS data
FROM times
LEFT JOIN
((SELECT "ItemAct".created_at, 0 as airdrop,
2022-11-15 20:51:55 +00:00
CASE WHEN "Item"."parentId" IS NULL THEN 0 ELSE "ItemAct".msats END as comment,
CASE WHEN "Item"."parentId" IS NULL THEN "ItemAct".msats ELSE 0 END as post
2022-06-24 15:38:00 +00:00
FROM "ItemAct"
2022-12-01 21:31:04 +00:00
JOIN "Item" on "ItemAct"."itemId" = "Item".id
2022-12-01 23:14:16 +00:00
WHERE ${intervalClause(when, 'ItemAct', true)} "ItemAct".act = 'TIP')
2022-06-24 15:38:00 +00:00
UNION ALL
2022-12-01 21:31:04 +00:00
(SELECT created_at, msats as airdrop, 0 as post, 0 as comment
2022-12-01 23:14:16 +00:00
FROM "Earn"
WHERE ${intervalClause(when, 'Earn', false)})) u ON time = date_trunc('${timeUnit(when)}', u.created_at)
2022-06-24 15:38:00 +00:00
GROUP BY time
ORDER BY time ASC`)
2022-06-10 19:20:33 +00:00
}
}
}