Module: database/repositories/runLogRepo

Data-access layer for the run_logs table (ENH-008).

Replaces the O(n²) JSON mutation pattern on runs.logs:

  • Every log line is stored as an independent row.
  • Writers call appendLog — a single INSERT.
  • Readers call getByRunId to retrieve all lines in order.

Schema

run_logs(id AUTOINCREMENT, runId TEXT, seq INT, level TEXT, message TEXT, createdAt TEXT)

Typical flow

// In runLogger.js (called for every log() invocation):
appendLog(run.id, 'info', '[12:34:56] Starting crawl…');

// In SSE route (initial snapshot):
const logs = getByRunId(runId).map(r => r.message);

Exports

  • appendLog — insert one log row
  • getByRunId — fetch all rows for a run, ordered by seq
  • deleteByRunId — hard-delete all logs for a run (purge path)
  • countByRunId — row count for a run (used in tests)
Source:

Members

(inner, constant) _seqCache :Map.<string, number>

runId → next seq value

Type:
  • Map.<string, number>
Source:

Methods

(static) appendLog(runId, level, message) → {void}

Append a single log line to the run_logs table.

This is the hot path — called on every log() invocation. It executes a single INSERT and returns immediately.

Parameters:
Name Type Description
runId string

The run this log line belongs to

level string

'info' | 'warn' | 'error'

message string

Pre-formatted log string (includes timestamp prefix)

Source:
Returns:
Type
void

(static) countByRunId(runId) → {number}

Count log rows for a run. Primarily used in tests to verify write behaviour.

Parameters:
Name Type Description
runId string
Source:
Returns:
Type
number

(static) deleteByRunId(runId) → {number}

Hard-delete all log rows for a run. Called when a run is permanently purged (recycle-bin purge path).

Parameters:
Name Type Description
runId string
Source:
Returns:

Number of rows deleted.

Type
number

(static) deleteByRunIds(runIds) → {number}

Hard-delete all log rows for multiple runs (batch purge). Used when a project is purged and all its runs are hard-deleted.

Parameters:
Name Type Description
runIds Array.<string>
Source:
Returns:

Total rows deleted.

Type
number

(static) evictCache(runId)

Evict a single run from the in-process seq cache. Called when a run reaches a terminal state (completed, failed, aborted) so the cache doesn't grow unboundedly on long-running servers.

Parameters:
Name Type Description
runId string
Source:

(static) getByRunId(runId) → {Array.<RunLogRow>}

Fetch all log rows for a run, ordered by seq ascending.

Returns the full row objects so callers can access level for filtering if needed. For plain string arrays (legacy API compat) use getByRunId(id).map(r => r.message).

Parameters:
Name Type Description
runId string
Source:
Returns:
Type
Array.<RunLogRow>

(static) getMessagesByRunId(runId) → {Array.<string>}

Fetch log messages (strings only) for a run, ordered by seq ascending. Convenience wrapper over getByRunId for callers that only need the message strings (e.g. the SSE snapshot and the run-detail REST endpoint).

Parameters:
Name Type Description
runId string
Source:
Returns:
Type
Array.<string>

(inner) nextSeq(db, runId) → {number}

Return the next sequence number for runId and advance the cache. Falls back to a DB MAX query on first access so restarts are safe.

Parameters:
Name Type Description
db Object

— better-sqlite3 Database instance

runId string
Source:
Returns:
Type
number

Type Definitions

RunLogRow

Type:
  • Object
Properties:
Name Type Description
id number

Auto-increment primary key

runId string

Foreign key → runs.id

seq number

1-based sequence number within the run

level string

'info' | 'warn' | 'error'

message string

Formatted log line (e.g. "[12:34:56] msg")

createdAt string

ISO 8601 timestamp

Source: