forked from wangziqi/ruoyi-vue-pro
feat(education): add content import persistence
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
-- EDU-011 persistence slice: tenant-owned import assets and durable preview/execute jobs.
|
||||
|
||||
CREATE TABLE education_content_import_asset (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
object_key VARCHAR(512) NOT NULL,
|
||||
file_name VARCHAR(255) NOT NULL,
|
||||
mime_type VARCHAR(128) NOT NULL,
|
||||
file_size_bytes BIGINT NOT NULL,
|
||||
checksum_sha256 VARCHAR(64) NOT NULL,
|
||||
creator VARCHAR(64) DEFAULT '',
|
||||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updater VARCHAR(64) DEFAULT '',
|
||||
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
CONSTRAINT ck_education_content_import_asset_size CHECK (file_size_bytes >= 0),
|
||||
CONSTRAINT uk_education_content_import_asset_tenant_id UNIQUE (tenant_id, id),
|
||||
CONSTRAINT uk_education_content_import_asset_object UNIQUE (tenant_id, object_key)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE education_content_import_asset IS '教育内容导入源文件元数据;文件存储与扫描由 Infra 持有';
|
||||
COMMENT ON COLUMN education_content_import_asset.object_key IS 'Infra 私有对象键,不存储公开 URL';
|
||||
|
||||
CREATE TABLE education_content_import_job (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
asset_id BIGINT NOT NULL,
|
||||
preview_key VARCHAR(128) NOT NULL,
|
||||
import_type VARCHAR(32) NOT NULL,
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'PREVIEW',
|
||||
attempt_count INTEGER NOT NULL DEFAULT 0,
|
||||
max_attempts INTEGER NOT NULL DEFAULT 3,
|
||||
next_attempt_at TIMESTAMP,
|
||||
locked_by VARCHAR(128),
|
||||
lease_token VARCHAR(64),
|
||||
lease_expires_at TIMESTAMP,
|
||||
last_heartbeat_at TIMESTAMP,
|
||||
started_at TIMESTAMP,
|
||||
finished_at TIMESTAMP,
|
||||
error_message VARCHAR(2000),
|
||||
preview_payload JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
result_summary JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
creator VARCHAR(64) DEFAULT '',
|
||||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updater VARCHAR(64) DEFAULT '',
|
||||
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
CONSTRAINT fk_education_content_import_job_asset_tenant
|
||||
FOREIGN KEY (tenant_id, asset_id)
|
||||
REFERENCES education_content_import_asset (tenant_id, id),
|
||||
CONSTRAINT uk_education_content_import_job_preview UNIQUE (tenant_id, preview_key),
|
||||
CONSTRAINT ck_education_content_import_job_status
|
||||
CHECK (status IN ('PREVIEW', 'PENDING', 'PROCESSING', 'COMPLETED', 'FAILED')),
|
||||
CONSTRAINT ck_education_content_import_job_attempts
|
||||
CHECK (attempt_count >= 0 AND max_attempts > 0 AND attempt_count <= max_attempts),
|
||||
CONSTRAINT ck_education_content_import_job_lease CHECK (
|
||||
(status = 'PROCESSING' AND locked_by IS NOT NULL AND lease_token IS NOT NULL
|
||||
AND lease_expires_at IS NOT NULL AND last_heartbeat_at IS NOT NULL)
|
||||
OR
|
||||
(status <> 'PROCESSING' AND locked_by IS NULL AND lease_token IS NULL
|
||||
AND lease_expires_at IS NULL AND last_heartbeat_at IS NULL)
|
||||
)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE education_content_import_job IS '教育内容导入预览与执行作业';
|
||||
COMMENT ON COLUMN education_content_import_job.preview_key IS '租户内重复预览幂等键';
|
||||
COMMENT ON COLUMN education_content_import_job.lease_token IS '处理租约 fencing token';
|
||||
|
||||
CREATE INDEX idx_education_content_import_job_ready
|
||||
ON education_content_import_job (next_attempt_at, create_time, id)
|
||||
WHERE status = 'PENDING' AND deleted = false;
|
||||
CREATE INDEX idx_education_content_import_job_expired
|
||||
ON education_content_import_job (lease_expires_at, create_time, id)
|
||||
WHERE status = 'PROCESSING' AND deleted = false;
|
||||
Reference in New Issue
Block a user