more functional design principles
Some checks failed
ci/woodpecker/pr/pr Pipeline failed

This commit is contained in:
Madison Grubb
2026-02-17 11:17:52 -05:00
parent 1a566e2d80
commit c8d37c98f4
14 changed files with 357 additions and 321 deletions

View File

@@ -5,6 +5,19 @@
const locks = new Map()
/**
* Get or create a queue for a lock key.
* @param {string} lockKey - Lock key
* @returns {Promise<any>} Existing or new queue promise
*/
const getOrCreateQueue = (lockKey) => {
const existingQueue = locks.get(lockKey)
if (existingQueue) return existingQueue
const newQueue = Promise.resolve()
locks.set(lockKey, newQueue)
return newQueue
}
/**
* Acquire a lock for a key and execute callback.
* Only one callback per key executes at a time.
@@ -14,12 +27,7 @@ const locks = new Map()
*/
export async function acquire(key, callback) {
const lockKey = String(key)
let queue = locks.get(lockKey)
if (!queue) {
queue = Promise.resolve()
locks.set(lockKey, queue)
}
const queue = getOrCreateQueue(lockKey)
const next = queue.then(() => callback()).finally(() => {
if (locks.get(lockKey) === next) {

View File

@@ -15,21 +15,20 @@ const TRADITIONAL_DELIMITER = Buffer.from('</event>', 'utf8')
/**
* @param {Buffer} buf
* @param {number} offset
* @param {number} value - Accumulated value
* @param {number} shift - Current bit shift
* @param {number} bytesRead - Bytes consumed so far
* @returns {{ value: number, bytesRead: number }} Decoded varint and bytes consumed.
*/
function readVarint(buf, offset) {
let value = 0
let shift = 0
let bytesRead = 0
while (offset + bytesRead < buf.length) {
const b = buf[offset + bytesRead]
bytesRead += 1
value += (b & 0x7F) << shift
if ((b & 0x80) === 0) return { value, bytesRead }
shift += 7
if (shift > 28) return { value: 0, bytesRead: 0 }
}
return { value, bytesRead }
function readVarint(buf, offset, value = 0, shift = 0, bytesRead = 0) {
if (offset + bytesRead >= buf.length) return { value, bytesRead }
const b = buf[offset + bytesRead]
const newValue = value + ((b & 0x7F) << shift)
const newBytesRead = bytesRead + 1
if ((b & 0x80) === 0) return { value: newValue, bytesRead: newBytesRead }
const newShift = shift + 7
if (newShift > 28) return { value: 0, bytesRead: 0 }
return readVarint(buf, offset, newValue, newShift, newBytesRead)
}
/**
@@ -127,12 +126,14 @@ export function parseCotPayload(payload) {
const uid = String(event['@_uid'] ?? event.uid ?? '')
const eventType = String(event['@_type'] ?? event.type ?? '')
const point = findInObject(parsed, 'point') ?? findInObject(event, 'point')
let lat = Number.NaN
let lng = Number.NaN
if (point && typeof point === 'object') {
lat = Number(point['@_lat'] ?? point.lat)
lng = Number(point['@_lon'] ?? point.lon ?? point['@_lng'] ?? point.lng)
const extractCoords = (pt) => {
if (!pt || typeof pt !== 'object') return { lat: Number.NaN, lng: Number.NaN }
return {
lat: Number(pt['@_lat'] ?? pt.lat),
lng: Number(pt['@_lon'] ?? pt.lon ?? pt['@_lng'] ?? pt.lng),
}
}
const { lat, lng } = extractCoords(point)
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null
const detail = findInObject(parsed, 'detail')

View File

@@ -5,11 +5,13 @@
import { SHUTDOWN_TIMEOUT_MS } from './constants.js'
const cleanupFunctions = []
let isShuttingDown = false
const shutdownState = {
isShuttingDown: false,
}
export function clearCleanup() {
cleanupFunctions.length = 0
isShuttingDown = false
shutdownState.isShuttingDown = false
}
export function registerCleanup(fn) {
@@ -17,17 +19,25 @@ export function registerCleanup(fn) {
cleanupFunctions.push(fn)
}
async function executeCleanup() {
if (isShuttingDown) return
isShuttingDown = true
for (let i = cleanupFunctions.length - 1; i >= 0; i--) {
try {
await cleanupFunctions[i]()
}
catch (error) {
console.error(`[shutdown] Cleanup function ${i} failed:`, error?.message || String(error))
}
const executeCleanupFunction = async (fn, index) => {
try {
await fn()
}
catch (error) {
console.error(`[shutdown] Cleanup function ${index} failed:`, error?.message || String(error))
}
}
const executeCleanupReverse = async (functions, index = functions.length - 1) => {
if (index < 0) return
await executeCleanupFunction(functions[index], index)
return executeCleanupReverse(functions, index - 1)
}
async function executeCleanup() {
if (shutdownState.isShuttingDown) return
shutdownState.isShuttingDown = true
await executeCleanupReverse(cleanupFunctions)
}
export async function graceful(error) {