Skip to content

Commit

Permalink
feat: return cached value and THEN refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
framp committed Sep 5, 2023
1 parent 3bd625e commit f1705a0
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 29 deletions.
25 changes: 12 additions & 13 deletions app/features/providers/github/commands/getPastEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,25 @@ import {
} from '~/features/providers/misc/http'
import { mapIssuesToEvents } from './misc/mapIssueToEvent'
import type { Event } from './types'
import { cache } from './misc/cache'
import { fetchCached } from './misc/cache'

export const getPastEvents = async (
nextToken?: String
): Promise<ApiResponse<Event[]>> => {
try {
if (cache.has('pastEvents')) {
return newSuccessfulResponse(cache.get('pastEvents'))
}

const client = newGraphQLClientFactory()
const res = await client<GetPastEventsQuery>(getPastEventsQuery, {
owner: 'cyprus-developer-community',
repo: 'events',
size: 20,
after: nextToken
})

const events = await mapIssuesToEvents(res.repository.issues.nodes)
cache.set('pastEvents', events, 60 * 60 * 24)
const cacheKey = 'pastEvents'
const events = await fetchCached(cacheKey, async () => {
const res = await client<GetPastEventsQuery>(getPastEventsQuery, {
owner: 'cyprus-developer-community',
repo: 'events',
size: 20,
after: nextToken
})

return mapIssuesToEvents(res.repository.issues.nodes)
})
return newSuccessfulResponse(events)
} catch (e) {
return newErrorResponse(e)
Expand Down
25 changes: 12 additions & 13 deletions app/features/providers/github/commands/getUpcomingEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,25 @@ import {
} from '~/features/providers/misc/http'
import type { Event } from './types'
import { mapIssuesToEvents } from './misc/mapIssueToEvent'
import { cache } from './misc/cache'
import { fetchCached } from './misc/cache'

export const getUpcomingEvents = async (
nextToken?: String
): Promise<ApiResponse<Event[]>> => {
try {
if (cache.has('upcomingEvents')) {
return newSuccessfulResponse(cache.get('upcomingEvents'))
}

const client = newGraphQLClientFactory()
const res = await client<GetUpcomingEventsQuery>(getUpcomingEventsQuery, {
owner: 'cyprus-developer-community',
repo: 'events',
size: 20,
after: nextToken
})

const events = await mapIssuesToEvents(res.repository.issues.nodes)
cache.set('upcomingEvents', events, 60 * 60 * 24)
const cacheKey = 'upcomingEvents'
const events = await fetchCached(cacheKey, async () => {
const res = await client<GetUpcomingEventsQuery>(getUpcomingEventsQuery, {
owner: 'cyprus-developer-community',
repo: 'events',
size: 20,
after: nextToken
})

return mapIssuesToEvents(res.repository.issues.nodes)
})
return newSuccessfulResponse(events)
} catch (e) {
return newErrorResponse(e)
Expand Down
38 changes: 35 additions & 3 deletions app/features/providers/github/commands/misc/cache.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
import NodeCache from 'node-cache'

let cache: NodeCache
let expired = {}

declare global {
var __cache: NodeCache | undefined
var __expired: { [key: string]: boolean }
}

if (process.env.NODE_ENV === 'production') {
cache = new NodeCache()
cache = new NodeCache({ deleteOnExpire: false })
} else {
if (!global.__cache) {
global.__cache = new NodeCache()
global.__cache = new NodeCache({ deleteOnExpire: false })
}
cache = global.__cache
if (!global.__expired) {
global.__expired = {}
}
expired = global.__expired
}

cache.on('expired', (key) => {
expired[key] = true
})

const fetchCached = async <T>(
cacheKey: string,
fetcher: () => Promise<T>,
ttl = 60 * 60 * 24
) => {
let response: T
if (cache.has(cacheKey)) {
response = cache.get(cacheKey)
if (expired[cacheKey]) {
;(async () => {
expired[cacheKey] = false
cache.set(cacheKey, await fetcher(), ttl)
})()
}
return response
}
response = await fetcher()
cache.set(cacheKey, response, ttl)
return response
}

export { cache }
export { cache, fetchCached }

0 comments on commit f1705a0

Please sign in to comment.