From 696437647b3615ab744582f64fc9576e78e777b5 Mon Sep 17 00:00:00 2001 From: Ben Allfree Date: Mon, 26 Dec 2022 11:11:08 +0000 Subject: [PATCH] cache pocketbase releases --- .../daemon/src/services/PocketBaseService.ts | 40 ++++--------------- .../daemon/src/util/downloadAndExtract.ts | 30 ++++++++++++++ packages/daemon/src/util/smartFetch.ts | 20 ++++++++++ readme.md | 14 ++++++- 4 files changed, 70 insertions(+), 34 deletions(-) create mode 100644 packages/daemon/src/util/downloadAndExtract.ts create mode 100644 packages/daemon/src/util/smartFetch.ts diff --git a/packages/daemon/src/services/PocketBaseService.ts b/packages/daemon/src/services/PocketBaseService.ts index d62fbdf5..2e226e10 100644 --- a/packages/daemon/src/services/PocketBaseService.ts +++ b/packages/daemon/src/services/PocketBaseService.ts @@ -1,18 +1,18 @@ import { createTimerManager } from '@pockethost/common' import { keys } from '@s-libs/micro-dash' import { spawn } from 'child_process' -import { chmodSync, existsSync } from 'fs' +import { existsSync } from 'fs' import getPort from 'get-port' -import fetch from 'node-fetch' import { type } from 'os' -import { dirname, join } from 'path' +import { join } from 'path' import { maxSatisfying, rsort } from 'semver' import { AsyncReturnType } from 'type-fest' -import { Extract } from 'unzipper' import { DAEMON_PB_DATA_DIR } from '../constants' +import { downloadAndExtract } from '../util/downloadAndExtract' import { mkInternalAddress, mkInternalUrl } from '../util/internal' import { dbg, error } from '../util/logger' import { safeCatch } from '../util/promiseHelper' +import { smartFetch } from '../util/smartFetch' import { tryFetch } from '../util/tryFetch' import { mkSingleton } from './mkSingleton' @@ -50,31 +50,6 @@ export type Release = { } export type Releases = Release[] -export const downloadAndExtract = async (url: string, binPath: string) => { - await new Promise(async (resolve, reject) => { - dbg(`Fetching ${url}`) - const res = await fetch(url) - if (!res.body) { - throw new Error(`Body expected for ${url}`) - } - dbg(`Extracting ${url}`) - const stream = res.body.pipe(Extract({ path: dirname(binPath) })) - stream.on('close', () => { - dbg(`Close ${url}`) - resolve() - }) - stream.on('error', (e) => { - error(`Error ${url} ${e}`) - reject() - }) - stream.on('end', () => { - dbg(`End ${url}`) - resolve() - }) - }) - chmodSync(binPath, 0o775) -} - export const createPocketbaseService = async ( config: PocketbaseServiceConfig ) => { @@ -90,10 +65,11 @@ export const createPocketbaseService = async ( let maxVersion = '' const check = async () => { - const res = await fetch( - `https://api.github.com/repos/pocketbase/pocketbase/releases` + const releases = await smartFetch( + `https://api.github.com/repos/pocketbase/pocketbase/releases`, + join(cachePath, `releases.json`) ) - const releases = (await res.json()) as Releases + dbg({ releases }) const promises = releases.map(async (release) => { const { tag_name, prerelease, assets } = release diff --git a/packages/daemon/src/util/downloadAndExtract.ts b/packages/daemon/src/util/downloadAndExtract.ts new file mode 100644 index 00000000..cf679330 --- /dev/null +++ b/packages/daemon/src/util/downloadAndExtract.ts @@ -0,0 +1,30 @@ +import { chmodSync } from 'fs' +import fetch from 'node-fetch' +import { dirname } from 'path' +import { Extract } from 'unzipper' +import { dbg, error } from './logger' + +export const downloadAndExtract = async (url: string, binPath: string) => { + await new Promise(async (resolve, reject) => { + dbg(`Fetching ${url}`) + const res = await fetch(url) + if (!res.body) { + throw new Error(`Body expected for ${url}`) + } + dbg(`Extracting ${url}`) + const stream = res.body.pipe(Extract({ path: dirname(binPath) })) + stream.on('close', () => { + dbg(`Close ${url}`) + resolve() + }) + stream.on('error', (e) => { + error(`Error ${url} ${e}`) + reject() + }) + stream.on('end', () => { + dbg(`End ${url}`) + resolve() + }) + }) + chmodSync(binPath, 0o775) +} diff --git a/packages/daemon/src/util/smartFetch.ts b/packages/daemon/src/util/smartFetch.ts new file mode 100644 index 00000000..0bc4786a --- /dev/null +++ b/packages/daemon/src/util/smartFetch.ts @@ -0,0 +1,20 @@ +import { existsSync, readFileSync, writeFileSync } from 'fs' +import fetch from 'node-fetch' +import { dbg } from './logger' + +export const smartFetch = async ( + url: string, + path: string +): Promise => { + const res = await fetch(url) + if (res.status !== 200) { + if (!existsSync(path)) { + throw new Error(`API down and no cache`) + } + dbg(`Using data from cache`) + return JSON.parse(readFileSync(path).toString()) as TRet + } + const data = await res.json() + writeFileSync(path, JSON.stringify(data)) + return data as TRet +} diff --git a/readme.md b/readme.md index fd296f72..0ba03aea 100644 --- a/readme.md +++ b/readme.md @@ -130,10 +130,20 @@ If all goes well: # Release History -**next** +**soon** - Proxy localhost paths to avoid local DNS setup -- Query pocketbase versions from github instead + +**next** + +- Cache pocketbase releases + +**0.5.7** + +- Fix various production errors +- Support PATCH and DELETE CORS operations +- Add pm2 production support +- Implement auto-upgrade feature and semver tagging **0.5.6**