trigger streak when eligible

This commit is contained in:
keyan 2023-02-02 13:47:09 -06:00
parent d24b0727ea
commit b3f7f24cff
4 changed files with 67 additions and 7 deletions

View File

@ -2,17 +2,17 @@ import { Badge, OverlayTrigger, Tooltip } from 'react-bootstrap'
import CowboyHatIcon from '../svgs/cowboy.svg' import CowboyHatIcon from '../svgs/cowboy.svg'
export default function CowboyHat ({ streak, badge, className = 'ml-1', height = 16, width = 16 }) { export default function CowboyHat ({ streak, badge, className = 'ml-1', height = 16, width = 16 }) {
if (!streak) { if (streak === null) {
return null return null
} }
return ( return (
<HatTooltip overlayText={`${streak} days`}> <HatTooltip overlayText={streak ? `${streak} days` : 'new'}>
{badge {badge
? ( ? (
<Badge variant='grey-medium' className='ml-2 d-inline-flex align-items-center'> <Badge variant='grey-medium' className='ml-2 d-inline-flex align-items-center'>
<CowboyHatIcon className={className} height={height} width={width} /> <CowboyHatIcon className={className} height={height} width={width} />
<span className='ml-1'>{streak}</span> <span className='ml-1'>{streak || 'new'}</span>
</Badge>) </Badge>)
: <CowboyHatIcon className={className} height={height} width={width} />} : <CowboyHatIcon className={className} height={height} width={width} />}
</HatTooltip> </HatTooltip>
@ -25,7 +25,7 @@ function HatTooltip ({ children, overlayText, placement }) {
placement={placement || 'bottom'} placement={placement || 'bottom'}
overlay={ overlay={
<Tooltip> <Tooltip>
{overlayText || '1 sat'} {overlayText}
</Tooltip> </Tooltip>
} }
trigger={['hover', 'focus']} trigger={['hover', 'focus']}

View File

@ -0,0 +1,14 @@
CREATE OR REPLACE FUNCTION user_streak_check() RETURNS TRIGGER AS $$
DECLARE
BEGIN
INSERT INTO pgboss.job (name, data) VALUES ('checkStreak', jsonb_build_object('id', NEW.id));
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS user_streak ON users;
CREATE TRIGGER user_streak
AFTER UPDATE ON users
FOR EACH ROW
WHEN (NEW.msats < OLD.msats)
EXECUTE PROCEDURE user_streak_check();

View File

@ -10,7 +10,7 @@ const { earn } = require('./earn')
const { ApolloClient, HttpLink, InMemoryCache } = require('@apollo/client') const { ApolloClient, HttpLink, InMemoryCache } = require('@apollo/client')
const { indexItem, indexAllItems } = require('./search') const { indexItem, indexAllItems } = require('./search')
const { timestampItem } = require('./ots') const { timestampItem } = require('./ots')
const { computeStreaks } = require('./streak') const { computeStreaks, checkStreak } = require('./streak')
const fetch = require('cross-fetch') const fetch = require('cross-fetch')
async function work () { async function work () {
@ -49,6 +49,7 @@ async function work () {
await boss.work('auction', auction(args)) await boss.work('auction', auction(args))
await boss.work('earn', earn(args)) await boss.work('earn', earn(args))
await boss.work('streak', computeStreaks(args)) await boss.work('streak', computeStreaks(args))
await boss.work('checkStreak', checkStreak(args))
console.log('working jobs') console.log('working jobs')
} }

View File

@ -1,3 +1,5 @@
const STREAK_THRESHOLD = 100
function computeStreaks ({ models }) { function computeStreaks ({ models }) {
return async function () { return async function () {
console.log('computing streaks') console.log('computing streaks')
@ -19,7 +21,7 @@ function computeStreaks ({ models }) {
WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago' - interval '1 day')::date
)) spending )) spending
GROUP BY "userId" GROUP BY "userId"
HAVING sum(sats_spent) >= 100 HAVING sum(sats_spent) >= ${STREAK_THRESHOLD}
), existing_streaks (id) AS ( ), existing_streaks (id) AS (
SELECT "userId" SELECT "userId"
FROM "Streak" FROM "Streak"
@ -48,4 +50,47 @@ function computeStreaks ({ models }) {
} }
} }
module.exports = { computeStreaks } function checkStreak ({ models }) {
return async function ({ data: { id } }) {
console.log('checking streak', id)
// if user is actively streaking skip
const streak = await models.streak.findFirst({
where: {
userId: Number(id),
endedAt: null
}
})
if (streak) {
console.log('done checking streak', id)
return
}
await models.$executeRaw`
WITH streak_started (id) AS (
SELECT "userId"
FROM
((SELECT "userId", floor(sum("ItemAct".msats)/1000) as sats_spent
FROM "ItemAct"
WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago')::date
AND "userId" = ${Number(id)}
GROUP BY "userId")
UNION ALL
(SELECT "userId", sats as sats_spent
FROM "Donation"
WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago')::date = (now() AT TIME ZONE 'America/Chicago')::date
AND "userId" = ${Number(id)}
)) spending
GROUP BY "userId"
HAVING sum(sats_spent) >= ${STREAK_THRESHOLD}
)
INSERT INTO "Streak" ("userId", "startedAt", created_at, updated_at)
SELECT id, (now() AT TIME ZONE 'America/Chicago')::date, now_utc(), now_utc()
FROM streak_started`
console.log('done checking streak', id)
}
}
module.exports = { checkStreak, computeStreaks }