Files
crates/api/src/events.ts
T
2022-09-11 21:16:33 +10:00

92 lines
3.2 KiB
TypeScript

import { EventEmitter } from 'node:events';
import { setTimeout } from 'timers/promises';
import type Log from 'bunyan';
import type { Want } from '@prisma/client';
import { Pg } from './pg';
import { wantDetails } from './utils';
import routerAuth from './routers/router.auth';
export enum Events {
WantAdded = 'WantAdded',
StartupSync = 'StartupSync',
ListingsUpdated = 'ListingsUpdated',
Connection = 'Connection',
}
export default function createEvents(log: Log, pg: Pg, discogs, offers) {
const events = new EventEmitter({ captureRejections: true });
const connections = new Map();
async function populateListings(want: Want) {
try {
const listings = await discogs.listings(want);
return listings;
} catch (e) {
if (e.message === 'rate limited') {
log.warn('rate limited, trying again in 60s');
await setTimeout(60 * 1000);
return populateListings(want);
}
throw e;
}
}
events.on('error', function eventError(e) {
log.error('event error', e);
});
events.on(Events.WantAdded, async function wantAdded(want: Want) {
log.info({ event: Events.WantAdded, ...wantDetails(want) });
const listings = await populateListings(want);
log.info({ listings: listings.length, ...wantDetails(want) }, 'listings added');
events.emit(Events.ListingsUpdated);
});
events.on(Events.StartupSync, async function wantAdded() {
const wants = await pg.wantsToSync();
log.info({ event: Events.StartupSync, wants: wants.length });
for (const want of wants) {
const listings = await populateListings(want);
log.info({ listings: listings.length, ...wantDetails(want) }, 'listings added');
}
log.info({ wants: wants.length }, 'finished syncing');
events.emit(Events.ListingsUpdated);
});
events.on(Events.ListingsUpdated, async function listingsUpdated() {
const bundles = await offers.bundles();
log.info({ event: Events.ListingsUpdated, bundles: bundles.length });
// const bundle = {
// username: b[0]?.data.seller.username,
// seller: b[0]?.data.seller.id,
// shipsFrom: b[0]?.data.ships_from,
// total,
// currency: b[0]?.data.price.currency,
// shipping: '...',
// items,
// mentionsAustralia: shipping.toLowerCase().includes('australia'),
// mentionsWorldwide: shipping.toLowerCase().includes('world'),
// }
for (const bundle of bundles) {
log.info({ seller: bundle.seller, items: bundle.items.length }, 'generating offers...');
const listingIds = bundle.items.map(i => i.id);
const updatedOffers = await offers.generate(listingIds, 100, 30)
log.info({ offers: updatedOffers.length }, 'offers set');
}
log.info('offers up to date');
});
events.on(Events.Connection, async function onConnection({ ws, id }) {
connections.set(id, ws);
})
return events;
}