Skip to content

Database schema

The plugin owns four tables, created by Migration1717000000CreateFujinShuttleTables (with fujin_job.heartbeat_at and fujin_job.phase added by two follow-up migrations). All use BINARY(16) UUID primary keys and utf8mb4.

fujin_profile ──1:N──► fujin_profile_column
      └──1:N──► fujin_job ──1:N──► fujin_job_log

fujin_profile

A saved import/export configuration.

Column Type Notes
id BINARY(16) PK.
name VARCHAR(255) Human label.
data_type VARCHAR(64) One of the seven types.
transfer_mode VARCHAR(16) import or export.
options JSON nullable Per-run options (batch size, reindex mode, concurrency, parent category, …).
file_path VARCHAR(1024) nullable Attached CSV path.
created_at DATETIME(3)
updated_at DATETIME(3) nullable

fujin_profile_column

The columns detected from the profile's CSV header (ON DELETE CASCADE with the profile).

Column Type Notes
id BINARY(16) PK.
profile_id BINARY(16) FK → fujin_profile.id.
field VARCHAR(255) CSV header name.
alias VARCHAR(255) Mapped logical field.
position INT (default 0) Column order.
options JSON nullable Column-level options.
created_at DATETIME(3)

fujin_job

One execution of a profile. profile_id is ON DELETE SET NULL, so a job's history survives deleting its profile.

Column Type Notes
id BINARY(16) PK.
profile_id BINARY(16) nullable FK → fujin_profile.id (SET NULL).
status VARCHAR(16) (default pending) See lifecycle.
phase VARCHAR(32) nullable resolvingimportingreindexing.
total INT (default 0) Total source rows.
processed INT (default 0) Rows processed so far.
progress INT (default 0) Percent (live caps below 100; 100 on finish).
heartbeat_at DATETIME(3) nullable Liveness stamp bumped by the run monitor.
stats JSON nullable Final per-status counts (success, no-change, errors, warnings, empty).
lock_token VARCHAR(64) nullable Internal lock for the duplicate-run guard.
started_at DATETIME(3) nullable
finished_at DATETIME(3) nullable
created_at DATETIME(3)

fujin_job_log

Per-row notices and errors (ON DELETE CASCADE with the job).

Column Type Notes
id BINARY(16) PK.
job_id BINARY(16) FK → fujin_job.id.
level VARCHAR(16) ERROR / WARNING / INFO / DEBUG.
row_no INT (default 0) Source row number (0 for non-row messages).
action VARCHAR(32) nullable e.g. created / updated / skipped.
message TEXT The message.
created_at DATETIME(3)

Job lifecycle

stateDiagram-v2
    [*] --> pending
    pending --> running
    running --> finished
    running --> stopping: Stop pressed
    stopping --> stopped
    running --> error
    pending --> error: stale heartbeat reaped
Status Meaning
pending Created; queued, waiting for a worker (or about to run inline).
running Executing — phase, processed, progress and heartbeat_at update live.
stopping A stop was requested; the run ends at the next batch boundary.
stopped Stopped by request — partial data is kept (no cross-batch transaction).
finished Completed; progress = 100, stats finalised.
error Failed, or reaped because its heartbeat went stale (worker crashed/killed).

The duplicate-run guard refuses a new run while a profile has an active job (pending/running/stopping); a stale heartbeat_at lets a dead job be reaped so the profile isn't blocked forever. See Concepts → tracking a run.

Querying jobs directly

-- Recent runs
SELECT HEX(id) AS job, HEX(profile_id) AS profile, status, phase,
       processed, total, progress, started_at, finished_at
FROM fujin_job ORDER BY created_at DESC LIMIT 20;

-- Errors for a job
SELECT row_no, action, message
FROM fujin_job_log
WHERE job_id = UNHEX('<jobHex>') AND level = 'ERROR'
ORDER BY row_no;