From 80f10f528d038acad7ab88b84977927cb3c34be8 Mon Sep 17 00:00:00 2001 From: Ben Allfree Date: Sun, 20 Nov 2022 09:14:48 -0800 Subject: [PATCH] refactor: logging and async services --- packages/common/src/Logger.ts | 27 +++++ packages/common/src/PromiseHelper.ts | 57 +++++++++ packages/common/src/index.ts | 3 + .../pocketbase-client-helpers/RpcHelper.ts | 110 ++++++++++++++++++ .../pocketbase-client-helpers/WatchHelper.ts | 72 ++++++++++++ .../src/pocketbase-client-helpers/index.ts | 2 + packages/daemon/src/db/BackupMixin.ts | 2 +- packages/daemon/src/db/InstanceMIxin.ts | 4 +- packages/daemon/src/db/InvocationMixin.ts | 4 +- packages/daemon/src/db/JobMixin.ts | 2 +- packages/daemon/src/db/PbClient.ts | 5 +- packages/daemon/src/migrate/migrate.ts | 8 +- packages/daemon/src/migrate/pexec.ts | 10 +- packages/daemon/src/migrate/withInstance.ts | 13 +-- packages/daemon/src/server.ts | 11 +- packages/daemon/src/services/BackupService.ts | 4 +- .../daemon/src/services/InstanceService.ts | 8 +- packages/daemon/src/services/JobService.ts | 4 +- packages/daemon/src/services/ProxyService.ts | 4 +- packages/daemon/src/util/backupInstance.ts | 8 +- packages/daemon/src/util/dbg.ts | 14 --- packages/daemon/src/util/ensureDirExists.ts | 2 +- packages/daemon/src/util/logger.ts | 5 + packages/daemon/src/util/promiseHelper.ts | 5 + packages/daemon/src/util/safeAsync.ts | 66 ----------- packages/daemon/src/util/spawnInstance.ts | 6 +- packages/daemon/src/util/tryFetch.ts | 4 +- packages/pockethost.io/package.json | 2 +- .../src/components/CodeSample.svelte | 5 +- .../src/components/helpers/Protect.svelte | 3 +- .../src/pocketbase/PocketbaseClient.ts | 62 ++++------ .../pockethost.io/src/pocketbase/index.ts | 9 +- .../app/instances/[instanceId]/+layout.svelte | 5 +- .../app/instances/[instanceId]/Backup.svelte | 4 +- .../src/routes/dashboard/+page.svelte | 3 +- packages/pockethost.io/src/util/database.ts | 23 ++-- packages/pockethost.io/src/util/logger.ts | 5 + packages/pockethost.io/src/util/safeCatch.ts | 16 --- packages/pockethost.io/src/util/stores.ts | 5 +- readme.md | 2 +- 40 files changed, 396 insertions(+), 208 deletions(-) create mode 100644 packages/common/src/Logger.ts create mode 100644 packages/common/src/PromiseHelper.ts create mode 100644 packages/common/src/pocketbase-client-helpers/RpcHelper.ts create mode 100644 packages/common/src/pocketbase-client-helpers/WatchHelper.ts create mode 100644 packages/common/src/pocketbase-client-helpers/index.ts delete mode 100644 packages/daemon/src/util/dbg.ts create mode 100644 packages/daemon/src/util/logger.ts create mode 100644 packages/daemon/src/util/promiseHelper.ts delete mode 100644 packages/daemon/src/util/safeAsync.ts create mode 100644 packages/pockethost.io/src/util/logger.ts delete mode 100644 packages/pockethost.io/src/util/safeCatch.ts diff --git a/packages/common/src/Logger.ts b/packages/common/src/Logger.ts new file mode 100644 index 00000000..f6f17db8 --- /dev/null +++ b/packages/common/src/Logger.ts @@ -0,0 +1,27 @@ +export type Config = { + debug: boolean +} + +export type Logger = ReturnType + +export const createLogger = (config: Config) => { + const { debug } = config + const dbg = (...args: any[]) => { + if (!debug) return + console.log(`[DBG]`, ...args) + } + + const warn = (...args: any[]) => { + console.log(`[WARN]`, ...args) + } + + const info = (...args: any[]) => { + console.log(`[INFO]`, ...args) + } + + const error = (...args: any[]) => { + console.error(`[ERROR]`, ...args) + } + + return { dbg, warn, info, error } +} diff --git a/packages/common/src/PromiseHelper.ts b/packages/common/src/PromiseHelper.ts new file mode 100644 index 00000000..48622572 --- /dev/null +++ b/packages/common/src/PromiseHelper.ts @@ -0,0 +1,57 @@ +import { ClientResponseError } from 'pocketbase' +import { Logger } from './Logger' + +export type PromiseHelperConfig = { + logger: Logger +} + +export type PromiseHelper = ReturnType + +export const createPromiseHelper = (config: PromiseHelperConfig) => { + const { logger } = config + const { dbg, error, warn } = logger + + let inside = '' + let c = 0 + const safeCatch = ( + name: string, + cb: (...args: TIn) => Promise + ) => { + return (...args: TIn) => { + const _c = c++ + const uuid = `${name}:${_c}` + const pfx = `[safeCatch:${uuid}]` + // dbg(uuid, ...args) + const tid = setTimeout(() => { + warn(pfx, `timeout waiting for ${pfx}`) + }, 100) + + inside = pfx + return cb(...args) + .then((res) => { + // dbg(uuid, `finished`) + inside = '' + clearTimeout(tid) + return res + }) + .catch((e: any) => { + if (e instanceof ClientResponseError) { + error(pfx, `PocketBase API error ${e}`) + error(pfx, JSON.stringify(e.data, null, 2)) + if (e.status === 400) { + error( + pfx, + `It looks like you don't have permission to make this request.` + ) + } + } else { + error(pfx, `failed: ${e}`) + } + error(pfx, e) + throw e + }) + } + } + + return { safeCatch } +} diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 74e97ed3..2348ce16 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,4 +1,7 @@ export * from './assert' +export * from './Logger' +export * from './pocketbase-client-helpers' +export * from './PromiseHelper' export * from './releases' export * from './schema' export * from './TimerManager' diff --git a/packages/common/src/pocketbase-client-helpers/RpcHelper.ts b/packages/common/src/pocketbase-client-helpers/RpcHelper.ts new file mode 100644 index 00000000..21b6bc29 --- /dev/null +++ b/packages/common/src/pocketbase-client-helpers/RpcHelper.ts @@ -0,0 +1,110 @@ +import type pocketbaseEs from 'pocketbase' +import type { RecordSubscription } from 'pocketbase' +import type { JsonObject } from 'type-fest' +import { Logger } from '../Logger' +import { PromiseHelper } from '../PromiseHelper' +import { RecordId, RpcCommands, UserId } from '../schema' +import type { WatchHelper } from './WatchHelper' + +export type RpcHelperConfig = { + client: pocketbaseEs + watchHelper: WatchHelper + promiseHelper: PromiseHelper + logger: Logger +} + +export type RpcHelper = ReturnType + +export enum RpcStatus { + New = 'new', + Queued = 'queued', + Running = 'running', + Starting = 'starting', + FinishedSuccess = 'finished-success', + FinishedError = 'finished-error', +} + +export type RpcPayloadBase = JsonObject + +export type RpcRecord_In> = Pick< + TRecord, + 'userId' | 'payload' | 'cmd' +> + +export type RpcRecord< + TPayload extends RpcPayloadBase, + TRes extends JsonObject +> = { + id: RecordId + userId: UserId + cmd: string + payload: TPayload + status: RpcStatus + message: string + result: TRes +} + +export const RPC_COLLECTION = `rpc` + +export const createRpcHelper = (config: RpcHelperConfig) => { + const { + client, + watchHelper: { watchById }, + promiseHelper: { safeCatch }, + } = config + + const mkRpc = ( + cmd: RpcCommands + ) => { + type ConcreteRpcRecord = RpcRecord + + return safeCatch( + cmd, + async ( + payload: TPayload, + cb?: (data: RecordSubscription) => void + ) => { + const _user = client.authStore.model + if (!_user) { + throw new Error(`Expected authenticated user here.`) + } + const { id: userId } = _user + const rpcIn: RpcRecord_In = { + cmd, + userId, + payload, + } + const rec = await client + .collection(RPC_COLLECTION) + .create(rpcIn) + return new Promise( + async (resolve, reject) => { + const unsub = watchById( + RPC_COLLECTION, + rec.id, + (data) => { + if (data.record.status === RpcStatus.FinishedSuccess) { + unsub.then((u) => { + u() + resolve(data.record.result) + }) + return + } + if (data.record.status === RpcStatus.FinishedError) { + unsub.then((u) => { + reject(data.record.message) + u() + }) + return + } + cb?.(data) + } + ) + } + ) + } + ) + } + + return { mkRpc } +} diff --git a/packages/common/src/pocketbase-client-helpers/WatchHelper.ts b/packages/common/src/pocketbase-client-helpers/WatchHelper.ts new file mode 100644 index 00000000..d10494e7 --- /dev/null +++ b/packages/common/src/pocketbase-client-helpers/WatchHelper.ts @@ -0,0 +1,72 @@ +import type { RecordId } from '@pockethost/common' +import type pocketbaseEs from 'pocketbase' +import type { RecordSubscription, UnsubscribeFunc } from 'pocketbase' +import { Logger } from '../Logger' +import { PromiseHelper } from '../PromiseHelper' + +export type WatchHelperConfig = { + client: pocketbaseEs + promiseHelper: PromiseHelper + logger: Logger +} + +export type WatchHelper = ReturnType + +export const createWatchHelper = (config: WatchHelperConfig) => { + const { + client, + promiseHelper: { safeCatch }, + } = config + + const watchById = safeCatch( + `subscribe`, + async ( + collectionName: string, + id: RecordId, + cb: (data: RecordSubscription) => void, + initialFetch = true + ) => { + const unsub = await client + .collection(collectionName) + .subscribe(id, cb) + if (initialFetch) { + const initial = await client.collection(collectionName).getOne(id) + if (!initial) { + throw new Error(`Expected ${collectionName}.${id} to exist.`) + } + cb({ action: 'update', record: initial }) + } + return unsub + } + ) + + const watchAllById = safeCatch( + `watchAllById`, + async ( + collectionName: string, + idName: keyof TRec, + idValue: RecordId, + cb: (data: RecordSubscription) => void, + initialFetch = true + ): Promise => { + const unsub = client + .collection(collectionName) + .subscribe('*', (e) => { + // console.log(e.record.instanceId, id) + if (e.record[idName] !== idValue) return + cb(e) + }) + if (initialFetch) { + const existing = await client + .collection(collectionName) + .getFullList(100, { + filter: `${idName.toString()} = '${idValue}'`, + }) + existing.forEach((record) => cb({ action: 'init', record })) + } + return unsub + } + ) + + return { watchById, watchAllById } +} diff --git a/packages/common/src/pocketbase-client-helpers/index.ts b/packages/common/src/pocketbase-client-helpers/index.ts new file mode 100644 index 00000000..3ec5e103 --- /dev/null +++ b/packages/common/src/pocketbase-client-helpers/index.ts @@ -0,0 +1,2 @@ +export * from './RpcHelper' +export * from './WatchHelper' diff --git a/packages/daemon/src/db/BackupMixin.ts b/packages/daemon/src/db/BackupMixin.ts index a68206ce..ad4ea158 100644 --- a/packages/daemon/src/db/BackupMixin.ts +++ b/packages/daemon/src/db/BackupMixin.ts @@ -7,7 +7,7 @@ import { InstanceId, InstancesRecord, } from '@pockethost/common' -import { safeCatch } from '../util/safeAsync' +import { safeCatch } from '../util/promiseHelper' import { MixinContext } from './PbClient' export type BackupApi = ReturnType diff --git a/packages/daemon/src/db/InstanceMIxin.ts b/packages/daemon/src/db/InstanceMIxin.ts index d07e1eda..a690445e 100644 --- a/packages/daemon/src/db/InstanceMIxin.ts +++ b/packages/daemon/src/db/InstanceMIxin.ts @@ -8,8 +8,8 @@ import { import { reduce } from '@s-libs/micro-dash' import Bottleneck from 'bottleneck' import { endOfMonth, startOfMonth } from 'date-fns' -import { dbg } from '../util/dbg' -import { safeCatch } from '../util/safeAsync' +import { dbg } from '../util/logger' +import { safeCatch } from '../util/promiseHelper' import { MixinContext } from './PbClient' export type InstanceApi = ReturnType diff --git a/packages/daemon/src/db/InvocationMixin.ts b/packages/daemon/src/db/InvocationMixin.ts index 0f3a40f7..ce62772b 100644 --- a/packages/daemon/src/db/InvocationMixin.ts +++ b/packages/daemon/src/db/InvocationMixin.ts @@ -3,8 +3,8 @@ import { InvocationRecord, pocketNow, } from '@pockethost/common' -import { dbg } from '../util/dbg' -import { safeCatch } from '../util/safeAsync' +import { dbg } from '../util/logger' +import { safeCatch } from '../util/promiseHelper' import { InstanceApi } from './InstanceMIxin' import { MixinContext } from './PbClient' diff --git a/packages/daemon/src/db/JobMixin.ts b/packages/daemon/src/db/JobMixin.ts index 8d4088f1..ffbe3aa4 100644 --- a/packages/daemon/src/db/JobMixin.ts +++ b/packages/daemon/src/db/JobMixin.ts @@ -1,5 +1,5 @@ import { JobRecord, JobStatus } from '@pockethost/common' -import { safeCatch } from '../util/safeAsync' +import { safeCatch } from '../util/promiseHelper' import { MixinContext } from './PbClient' export enum RecordSubscriptionActions { diff --git a/packages/daemon/src/db/PbClient.ts b/packages/daemon/src/db/PbClient.ts index f550e93e..1cce0516 100644 --- a/packages/daemon/src/db/PbClient.ts +++ b/packages/daemon/src/db/PbClient.ts @@ -6,7 +6,8 @@ import { } from 'pocketbase' import { DAEMON_PB_DATA_DIR, PUBLIC_PB_SUBDOMAIN } from '../constants' import { Collection_Serialized } from '../migrate/schema' -import { safeCatch } from '../util/safeAsync' +import { info } from '../util/logger' +import { safeCatch } from '../util/promiseHelper' import { createBackupMixin } from './BackupMixin' import { createInstanceMixin } from './InstanceMIxin' import { createInvocationMixin } from './InvocationMixin' @@ -18,7 +19,7 @@ export type PocketbaseClientApi = ReturnType export type MixinContext = { client: pocketbaseEs; rawDb: Knex } export const createPbClient = (url: string) => { - console.log(`Initializing client: ${url}`) + info(`Initializing client: ${url}`) const rawDb = createRawPbClient( `${DAEMON_PB_DATA_DIR}/${PUBLIC_PB_SUBDOMAIN}/pb_data/data.db` ) diff --git a/packages/daemon/src/migrate/migrate.ts b/packages/daemon/src/migrate/migrate.ts index 1105e5b4..3f181682 100644 --- a/packages/daemon/src/migrate/migrate.ts +++ b/packages/daemon/src/migrate/migrate.ts @@ -7,8 +7,8 @@ import { PUBLIC_PB_SUBDOMAIN, } from '../constants' import { backupInstance } from '../util/backupInstance' -import { error } from '../util/dbg' -import { safeCatch } from '../util/safeAsync' +import { dbg, error, info } from '../util/logger' +import { safeCatch } from '../util/promiseHelper' import { pexec } from './pexec' import { schema } from './schema' import { withInstance } from './withInstance' @@ -20,11 +20,11 @@ safeCatch(`root`, async () => { PUBLIC_PB_SUBDOMAIN, `${+new Date()}`, async (progress) => { - console.log(progress) + dbg(progress) } ) - console.log(`Upgrading`) + info(`Upgrading`) await pexec(`${PB_BIN} upgrade --dir=pb_data`) await withInstance(async (client) => { diff --git a/packages/daemon/src/migrate/pexec.ts b/packages/daemon/src/migrate/pexec.ts index cc88e490..2c314d71 100644 --- a/packages/daemon/src/migrate/pexec.ts +++ b/packages/daemon/src/migrate/pexec.ts @@ -1,13 +1,15 @@ import { exec } from 'child_process' -import { safeCatch } from '../util/safeAsync' +import { dbg, error } from '../util/logger' +import { safeCatch } from '../util/promiseHelper' export const pexec = safeCatch(`pexec`, (cmd: string) => { return new Promise((resolve, reject) => { - console.log(cmd) + dbg(cmd) exec(cmd, (err, stdout, stderr) => { - console.log(stdout) - console.error(stderr) + dbg(stdout) if (err) { + error(`${err}`) + error(stderr) reject(err) return } diff --git a/packages/daemon/src/migrate/withInstance.ts b/packages/daemon/src/migrate/withInstance.ts index f10a5f13..3d69b93d 100644 --- a/packages/daemon/src/migrate/withInstance.ts +++ b/packages/daemon/src/migrate/withInstance.ts @@ -9,7 +9,8 @@ import { } from '../constants' import { createPbClient, PocketbaseClientApi } from '../db/PbClient' import { mkInternalUrl } from '../util/internal' -import { safeCatch } from '../util/safeAsync' +import { error, info } from '../util/logger' +import { safeCatch } from '../util/promiseHelper' import { spawnInstance } from '../util/spawnInstance' import { tryFetch } from '../util/tryFetch' @@ -31,18 +32,16 @@ export const withInstance = safeCatch( await client.adminAuthViaEmail(DAEMON_PB_USERNAME, DAEMON_PB_PASSWORD) await cb(client) } catch (e) { - console.error( + error( `***WARNING*** CANNOT AUTHENTICATE TO ${PUBLIC_PB_PROTOCOL}://${PUBLIC_PB_SUBDOMAIN}.${PUBLIC_PB_DOMAIN}/_/` ) - console.error( - `***WARNING*** LOG IN MANUALLY, ADJUST .env, AND RESTART DOCKER` - ) + error(`***WARNING*** LOG IN MANUALLY, ADJUST .env, AND RESTART DOCKER`) } finally { - console.log(`Exiting process`) + info(`Exiting process`) mainProcess.kill() } } catch (e) { - console.error(`${e}`) + error(`${e}`) } } ) diff --git a/packages/daemon/src/server.ts b/packages/daemon/src/server.ts index 34c5c358..2567b23a 100644 --- a/packages/daemon/src/server.ts +++ b/packages/daemon/src/server.ts @@ -13,6 +13,7 @@ import { createInstanceService } from './services/InstanceService' import { createJobService } from './services/JobService' import { createProxyService } from './services/ProxyService' import { mkInternalUrl } from './util/internal' +import { dbg, error, info } from './util/logger' import { spawnInstance } from './util/spawnInstance' // npm install eventsource --save global.EventSource = require('eventsource') @@ -36,14 +37,12 @@ global.EventSource = require('eventsource') const instanceService = await createInstanceService(client) try { await client.adminAuthViaEmail(DAEMON_PB_USERNAME, DAEMON_PB_PASSWORD) - console.log(`Logged in`) + dbg(`Logged in`) } catch (e) { - console.error( + error( `***WARNING*** CANNOT AUTHENTICATE TO ${PUBLIC_PB_PROTOCOL}://${PUBLIC_PB_SUBDOMAIN}.${PUBLIC_PB_DOMAIN}/_/` ) - console.error( - `***WARNING*** LOG IN MANUALLY, ADJUST .env, AND RESTART DOCKER` - ) + error(`***WARNING*** LOG IN MANUALLY, ADJUST .env, AND RESTART DOCKER`) } const proxyService = await createProxyService(instanceService) @@ -51,7 +50,7 @@ global.EventSource = require('eventsource') const backupService = await createBackupService(client, jobService) process.once('SIGUSR2', async () => { - console.log(`SIGUSR2 detected`) + info(`SIGUSR2 detected`) proxyService.shutdown() instanceService.shutdown() jobService.shutdown() diff --git a/packages/daemon/src/services/BackupService.ts b/packages/daemon/src/services/BackupService.ts index 840d57ab..6adbbca5 100644 --- a/packages/daemon/src/services/BackupService.ts +++ b/packages/daemon/src/services/BackupService.ts @@ -10,7 +10,7 @@ import { import Bottleneck from 'bottleneck' import { PocketbaseClientApi } from '../db/PbClient' import { backupInstance } from '../util/backupInstance' -import { dbg } from '../util/dbg' +import { dbg } from '../util/logger' import { JobServiceApi } from './JobService' export const createBackupService = async ( @@ -66,7 +66,7 @@ export const createBackupService = async ( tm.repeat(async () => { const backupRec = await client.getNextBackupJob() if (!backupRec) { - dbg(`No backups requested`) + // dbg(`No backups requested`) return true } const instance = await client.getInstance(backupRec.instanceId) diff --git a/packages/daemon/src/services/InstanceService.ts b/packages/daemon/src/services/InstanceService.ts index 6cc3fe2a..99d72e14 100644 --- a/packages/daemon/src/services/InstanceService.ts +++ b/packages/daemon/src/services/InstanceService.ts @@ -16,10 +16,10 @@ import { PUBLIC_APP_PROTOCOL, } from '../constants' import { PocketbaseClientApi } from '../db/PbClient' -import { dbg } from '../util/dbg' import { mkInternalUrl } from '../util/internal' +import { dbg, error, warn } from '../util/logger' import { now } from '../util/now' -import { safeCatch } from '../util/safeAsync' +import { safeCatch } from '../util/promiseHelper' import { PocketbaseProcess, spawnInstance } from '../util/spawnInstance' type InstanceApi = { @@ -68,7 +68,7 @@ export const createInstanceService = async (client: PocketbaseClientApi) => { port: DAEMON_PB_PORT_BASE, exclude, }).catch((e) => { - console.error(`Failed to get port for ${subdomain}`) + error(`Failed to get port for ${subdomain}`) throw e }) dbg(`Found port for ${subdomain}: ${newPort}`) @@ -81,7 +81,7 @@ export const createInstanceService = async (client: PocketbaseClientApi) => { port: newPort, bin: binFor(instance.platform, instance.version), onUnexpectedStop: (code) => { - console.warn(`${subdomain} exited unexpectedly with ${code}`) + warn(`${subdomain} exited unexpectedly with ${code}`) api.shutdown() }, }) diff --git a/packages/daemon/src/services/JobService.ts b/packages/daemon/src/services/JobService.ts index 15b91278..e86243a2 100644 --- a/packages/daemon/src/services/JobService.ts +++ b/packages/daemon/src/services/JobService.ts @@ -11,7 +11,7 @@ import { default as knexFactory } from 'knex' import pocketbaseEs from 'pocketbase' import { AsyncReturnType } from 'type-fest' import { PocketbaseClientApi } from '../db/PbClient' -import { error } from '../util/dbg' +import { dbg, error } from '../util/logger' export type JobServiceApi = AsyncReturnType @@ -46,7 +46,7 @@ export const createJobService = async (client: PocketbaseClientApi) => { if (!handler) { throw new Error(`Job handler ${cmd} is not registered`) } - console.log(`Running job ${job.id}`, job) + dbg(`Running job ${job.id}`, job) await client.setJobStatus(job, JobStatus.Running) await handler(job) await client.setJobStatus(job, JobStatus.FinishedSuccess) diff --git a/packages/daemon/src/services/ProxyService.ts b/packages/daemon/src/services/ProxyService.ts index 1809a1c9..4fd56123 100644 --- a/packages/daemon/src/services/ProxyService.ts +++ b/packages/daemon/src/services/ProxyService.ts @@ -7,8 +7,8 @@ import { PUBLIC_APP_PROTOCOL, PUBLIC_PB_SUBDOMAIN, } from '../constants' -import { dbg, info } from '../util/dbg' import { mkInternalUrl } from '../util/internal' +import { dbg, error, info } from '../util/logger' import { InstanceServiceApi } from './InstanceService' export type ProxyServiceApi = AsyncReturnType @@ -22,7 +22,7 @@ export const createProxyService = async ( dbg(`Incoming request ${req.headers.host}/${req.url}`) const die = (msg: string) => { - console.error(`ERROR: ${msg}`) + error(msg) res.writeHead(403, { 'Content-Type': `text/plain`, }) diff --git a/packages/daemon/src/util/backupInstance.ts b/packages/daemon/src/util/backupInstance.ts index b273f233..5449d45f 100644 --- a/packages/daemon/src/util/backupInstance.ts +++ b/packages/daemon/src/util/backupInstance.ts @@ -6,9 +6,9 @@ import { Database } from 'sqlite3' import tmp from 'tmp' import { DAEMON_PB_DATA_DIR } from '../constants' import { pexec } from '../migrate/pexec' -import { dbg, error } from './dbg' import { ensureDirExists } from './ensureDirExists' -import { safeCatch } from './safeAsync' +import { dbg, error } from './logger' +import { safeCatch } from './promiseHelper' export type BackupProgress = { current: number @@ -75,7 +75,7 @@ export const backupInstance = safeCatch( unsafeCleanup: true, }) const backupTmpTargetRoot = resolve(tmpObj.name) - console.log({ + dbg({ instanceId, dataRoot, backupTgzRoot, @@ -109,7 +109,7 @@ export const backupInstance = safeCatch( error(`${e}`) throw e } finally { - console.log(`Removing again ${backupTmpTargetRoot}`) + dbg(`Removing again ${backupTmpTargetRoot}`) tmpObj.removeCallback() chdir(_cwd) } diff --git a/packages/daemon/src/util/dbg.ts b/packages/daemon/src/util/dbg.ts deleted file mode 100644 index 4390e108..00000000 --- a/packages/daemon/src/util/dbg.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DEBUG } from '../constants' - -export const dbg = (...args: any[]) => { - if (!DEBUG) return - console.log(...args) -} - -export const info = (...args: any[]) => { - console.log(...args) -} - -export const error = (...args: any[]) => { - console.error(...args) -} diff --git a/packages/daemon/src/util/ensureDirExists.ts b/packages/daemon/src/util/ensureDirExists.ts index 898ecd59..5593391b 100644 --- a/packages/daemon/src/util/ensureDirExists.ts +++ b/packages/daemon/src/util/ensureDirExists.ts @@ -1,5 +1,5 @@ import { mkdirSync } from 'fs' -import { dbg } from './dbg' +import { dbg } from './logger' export const ensureDirExists = (path: string) => { try { diff --git a/packages/daemon/src/util/logger.ts b/packages/daemon/src/util/logger.ts new file mode 100644 index 00000000..09fb0b18 --- /dev/null +++ b/packages/daemon/src/util/logger.ts @@ -0,0 +1,5 @@ +import { createLogger } from '@pockethost/common' +import { DEBUG } from '../constants' + +export const logger = createLogger({ debug: DEBUG }) +export const { dbg, info, warn, error } = logger diff --git a/packages/daemon/src/util/promiseHelper.ts b/packages/daemon/src/util/promiseHelper.ts new file mode 100644 index 00000000..225742c6 --- /dev/null +++ b/packages/daemon/src/util/promiseHelper.ts @@ -0,0 +1,5 @@ +import { createPromiseHelper } from '@pockethost/common' +import { logger } from './logger' + +export const promiseHelper = createPromiseHelper({ logger }) +export const { safeCatch } = promiseHelper diff --git a/packages/daemon/src/util/safeAsync.ts b/packages/daemon/src/util/safeAsync.ts deleted file mode 100644 index df858b53..00000000 --- a/packages/daemon/src/util/safeAsync.ts +++ /dev/null @@ -1,66 +0,0 @@ -import Bottleneck from 'bottleneck' -import { ClientResponseError } from 'pocketbase' -import { dbg, error } from './dbg' - -const limiter = new Bottleneck({ maxConcurrent: 1 }) - -let inside = '' -export const serialAsync = ( - name: string, - cb: (...args: TIn) => Promise -) => { - const _cb = safeCatch(name, cb) - - return (...args: TIn) => { - return limiter.schedule(() => { - if (inside) { - throw new Error( - `Already in async function ${inside}, can't execute ${name}` - ) - } - return _cb(...args).finally(() => { - inside = '' - }) - }) - } -} - -let c = 0 -export const safeCatch = ( - name: string, - cb: (...args: TIn) => Promise -) => { - return (...args: TIn) => { - const _c = c++ - const uuid = `${name}:${_c}` - dbg(uuid, ...args) - const tid = setTimeout(() => { - dbg(uuid, `WARNING: timeout waiting for ${uuid}`) - }, 100) - - inside = uuid - return cb(...args) - .then((res) => { - dbg(uuid, `finished`) - inside = '' - clearTimeout(tid) - return res - }) - .catch((e: any) => { - if (e instanceof ClientResponseError) { - error(uuid, `PocketBase API error ${e}`) - error(uuid, JSON.stringify(e.data, null, 2)) - if (e.status === 400) { - error( - uuid, - `It looks like you don't have permission to make this request.` - ) - } - } else { - error(uuid, `failed: ${e}`) - } - error(uuid, e) - throw e - }) - } -} diff --git a/packages/daemon/src/util/spawnInstance.ts b/packages/daemon/src/util/spawnInstance.ts index 56ab6ab6..b1b30295 100644 --- a/packages/daemon/src/util/spawnInstance.ts +++ b/packages/daemon/src/util/spawnInstance.ts @@ -2,9 +2,9 @@ import { spawn } from 'child_process' import { existsSync } from 'fs' import { AsyncReturnType } from 'type-fest' import { DAEMON_PB_BIN_DIR, DAEMON_PB_DATA_DIR } from '../constants' -import { dbg } from './dbg' import { mkInternalAddress, mkInternalUrl } from './internal' -import { safeCatch } from './safeAsync' +import { dbg, error } from './logger' +import { safeCatch } from './promiseHelper' import { tryFetch } from './tryFetch' export type PocketbaseProcess = AsyncReturnType @@ -40,7 +40,7 @@ export const spawnInstance = safeCatch(`spawnInstance`, async (cfg: Config) => { }) ls.stderr.on('data', (data) => { - console.error(`${subdomain} stderr: ${data}`) + error(`${subdomain} stderr: ${data}`) }) ls.on('close', (code) => { diff --git a/packages/daemon/src/util/tryFetch.ts b/packages/daemon/src/util/tryFetch.ts index f16981f7..10b60205 100644 --- a/packages/daemon/src/util/tryFetch.ts +++ b/packages/daemon/src/util/tryFetch.ts @@ -1,5 +1,5 @@ -import { dbg, error } from './dbg' -import { safeCatch } from './safeAsync' +import { dbg, error } from './logger' +import { safeCatch } from './promiseHelper' export const tryFetch = safeCatch( `tryFetch`, diff --git a/packages/pockethost.io/package.json b/packages/pockethost.io/package.json index 136cbf66..b2f219b3 100644 --- a/packages/pockethost.io/package.json +++ b/packages/pockethost.io/package.json @@ -39,4 +39,4 @@ "sass": "^1.54.9", "svelte-highlight": "^6.2.1" } -} \ No newline at end of file +} diff --git a/packages/pockethost.io/src/components/CodeSample.svelte b/packages/pockethost.io/src/components/CodeSample.svelte index 5c031a44..a5728f6c 100644 --- a/packages/pockethost.io/src/components/CodeSample.svelte +++ b/packages/pockethost.io/src/components/CodeSample.svelte @@ -1,12 +1,13 @@ diff --git a/packages/pockethost.io/src/components/helpers/Protect.svelte b/packages/pockethost.io/src/components/helpers/Protect.svelte index 0cc7ff01..06ee0bf7 100644 --- a/packages/pockethost.io/src/components/helpers/Protect.svelte +++ b/packages/pockethost.io/src/components/helpers/Protect.svelte @@ -1,5 +1,6 @@