mirror of
https://github.com/langgenius/dify.git
synced 2026-09-02 14:25:35 +08:00
Import the committed KnowledgeFS snapshot dc4072ee302317145612087ce7440851dc329fd0 under knowledge-fs/ without its Git history, local IDE settings, or build artifacts.
264 lines
12 KiB
SQL
264 lines
12 KiB
SQL
-- Knowledge Platform schema migration
|
|
-- Migration id: 0020_profile_migration_runs
|
|
-- Dialect: postgres
|
|
|
|
-- A profile change over a populated space is a durable rebuild. The run freezes the old
|
|
-- publication, both old profile heads, and the immutable candidate revision before any worker
|
|
-- starts. Only the joint profile/publication CAS may make the candidate visible.
|
|
CREATE TABLE IF NOT EXISTS "knowledge_space_profile_migration_runs" (
|
|
"id" UUID PRIMARY KEY NOT NULL,
|
|
"tenant_id" VARCHAR(255) NOT NULL,
|
|
"knowledge_space_id" UUID NOT NULL,
|
|
"changed_kind" VARCHAR(16) NOT NULL,
|
|
"rebuild_scope" VARCHAR(48) NOT NULL,
|
|
"candidate_profile_kind" VARCHAR(16) NOT NULL,
|
|
"candidate_profile_revision_id" UUID NOT NULL,
|
|
"candidate_profile_revision" INTEGER NOT NULL,
|
|
"candidate_profile_snapshot_digest" CHAR(64) NOT NULL,
|
|
"base_embedding_profile_kind" VARCHAR(16),
|
|
"base_embedding_profile_revision_id" UUID,
|
|
"base_embedding_profile_revision" INTEGER,
|
|
"base_embedding_profile_snapshot_digest" CHAR(64),
|
|
"base_retrieval_profile_kind" VARCHAR(16) NOT NULL,
|
|
"base_retrieval_profile_revision_id" UUID NOT NULL,
|
|
"base_retrieval_profile_revision" INTEGER NOT NULL,
|
|
"base_retrieval_profile_snapshot_digest" CHAR(64) NOT NULL,
|
|
"base_publication_id" UUID NOT NULL,
|
|
"base_publication_fingerprint" VARCHAR(86) NOT NULL,
|
|
"base_publication_head_revision" INTEGER NOT NULL,
|
|
"candidate_publication_id" UUID,
|
|
"candidate_publication_fingerprint" VARCHAR(86),
|
|
"permission_snapshot_id" UUID NOT NULL,
|
|
"permission_snapshot_revision" INTEGER NOT NULL,
|
|
"requested_by_subject_id" VARCHAR(255) NOT NULL,
|
|
"access_channel" VARCHAR(16) NOT NULL,
|
|
"idempotency_key" VARCHAR(255) NOT NULL,
|
|
"idempotency_digest" CHAR(64) NOT NULL,
|
|
"run_state" VARCHAR(16) NOT NULL,
|
|
"active_slot" INTEGER,
|
|
"checkpoint" VARCHAR(32) NOT NULL,
|
|
"evaluation_summary" JSONB,
|
|
"execution_attempts" INTEGER NOT NULL,
|
|
"max_execution_attempts" INTEGER NOT NULL,
|
|
"worker_id" VARCHAR(255),
|
|
"lease_token" UUID,
|
|
"lease_expires_at" TIMESTAMPTZ,
|
|
"heartbeat_at" TIMESTAMPTZ,
|
|
"row_version" INTEGER NOT NULL,
|
|
"last_error_code" VARCHAR(64),
|
|
"last_error_message" TEXT,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"completed_at" TIMESTAMPTZ,
|
|
"canceled_at" TIMESTAMPTZ,
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_kind_ck"
|
|
CHECK (
|
|
"changed_kind" IN ('embedding', 'retrieval')
|
|
AND "candidate_profile_kind" = "changed_kind"
|
|
AND "base_retrieval_profile_kind" = 'retrieval'
|
|
AND ("base_embedding_profile_kind" IS NULL OR "base_embedding_profile_kind" = 'embedding')
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_scope_ck"
|
|
CHECK (
|
|
("changed_kind" = 'embedding' AND "rebuild_scope" = 'full-vector-space')
|
|
OR ("changed_kind" = 'retrieval' AND "rebuild_scope" IN (
|
|
'clone-publication', 'full-page-index-summary-outline'
|
|
))
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_state_ck"
|
|
CHECK ("run_state" IN ('queued', 'running', 'succeeded', 'failed', 'canceled')),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_checkpoint_ck"
|
|
CHECK ("checkpoint" IN ('queued', 'candidate-built', 'evaluated', 'activated')),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_idempotency_digest_ck"
|
|
CHECK ("idempotency_digest" ~ '^[a-f0-9]{64}$'),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_positive_ck"
|
|
CHECK (
|
|
"candidate_profile_revision" >= 1
|
|
AND "base_retrieval_profile_revision" >= 1
|
|
AND "base_publication_head_revision" >= 1
|
|
AND "permission_snapshot_revision" >= 1
|
|
AND "execution_attempts" >= 0
|
|
AND "max_execution_attempts" >= 1
|
|
AND "execution_attempts" <= "max_execution_attempts"
|
|
AND "row_version" >= 1
|
|
AND ("active_slot" IS NULL OR "active_slot" = 1)
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_embedding_ref_ck"
|
|
CHECK (
|
|
("base_embedding_profile_kind" IS NULL
|
|
AND "base_embedding_profile_revision_id" IS NULL
|
|
AND "base_embedding_profile_revision" IS NULL
|
|
AND "base_embedding_profile_snapshot_digest" IS NULL)
|
|
OR ("base_embedding_profile_kind" = 'embedding'
|
|
AND "base_embedding_profile_revision_id" IS NOT NULL
|
|
AND "base_embedding_profile_revision" >= 1
|
|
AND "base_embedding_profile_snapshot_digest" IS NOT NULL)
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_candidate_publication_ck"
|
|
CHECK (
|
|
("candidate_publication_id" IS NULL AND "candidate_publication_fingerprint" IS NULL)
|
|
OR ("candidate_publication_id" IS NOT NULL AND "candidate_publication_fingerprint" IS NOT NULL)
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_checkpoint_shape_ck"
|
|
CHECK (
|
|
(
|
|
"checkpoint" = 'queued'
|
|
AND "candidate_publication_id" IS NULL
|
|
AND "candidate_publication_fingerprint" IS NULL
|
|
AND "evaluation_summary" IS NULL
|
|
)
|
|
OR (
|
|
"checkpoint" = 'candidate-built'
|
|
AND "candidate_publication_id" IS NOT NULL
|
|
AND "candidate_publication_fingerprint" IS NOT NULL
|
|
AND "evaluation_summary" IS NULL
|
|
)
|
|
OR (
|
|
"checkpoint" IN ('evaluated', 'activated')
|
|
AND "candidate_publication_id" IS NOT NULL
|
|
AND "candidate_publication_fingerprint" IS NOT NULL
|
|
AND "evaluation_summary" IS NOT NULL
|
|
AND jsonb_typeof("evaluation_summary") = 'object'
|
|
)
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_lease_ck"
|
|
CHECK (
|
|
("run_state" = 'running' AND "worker_id" IS NOT NULL AND "lease_token" IS NOT NULL
|
|
AND "lease_expires_at" IS NOT NULL AND "heartbeat_at" IS NOT NULL)
|
|
OR ("run_state" <> 'running' AND "worker_id" IS NULL AND "lease_token" IS NULL
|
|
AND "lease_expires_at" IS NULL AND "heartbeat_at" IS NULL)
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_lease_token_ck"
|
|
CHECK (
|
|
"lease_token" IS NULL
|
|
OR "lease_token" <> '00000000-0000-0000-0000-000000000000'::uuid
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_runs_lifecycle_ck"
|
|
CHECK (
|
|
("run_state" IN ('queued', 'running') AND "active_slot" = 1 AND "completed_at" IS NULL
|
|
AND "canceled_at" IS NULL)
|
|
OR ("run_state" = 'succeeded' AND "checkpoint" = 'activated'
|
|
AND "active_slot" IS NULL AND "completed_at" IS NOT NULL AND "canceled_at" IS NULL
|
|
AND "last_error_code" IS NULL AND "last_error_message" IS NULL)
|
|
OR ("run_state" = 'failed' AND "completed_at" IS NOT NULL
|
|
AND "active_slot" IS NULL AND "canceled_at" IS NULL AND "last_error_code" IS NOT NULL
|
|
AND "last_error_message" IS NOT NULL)
|
|
OR ("run_state" = 'canceled' AND "completed_at" IS NOT NULL
|
|
AND "active_slot" IS NULL AND "canceled_at" IS NOT NULL)
|
|
),
|
|
FOREIGN KEY ("tenant_id", "knowledge_space_id")
|
|
REFERENCES "knowledge_spaces" ("tenant_id", "id") ON DELETE CASCADE,
|
|
FOREIGN KEY (
|
|
"tenant_id", "knowledge_space_id", "candidate_profile_kind",
|
|
"candidate_profile_revision_id", "candidate_profile_revision",
|
|
"candidate_profile_snapshot_digest"
|
|
) REFERENCES "knowledge_space_profile_revisions" (
|
|
"tenant_id", "knowledge_space_id", "kind", "id", "revision", "snapshot_digest"
|
|
) ON DELETE RESTRICT,
|
|
FOREIGN KEY (
|
|
"tenant_id", "knowledge_space_id", "base_embedding_profile_kind",
|
|
"base_embedding_profile_revision_id", "base_embedding_profile_revision",
|
|
"base_embedding_profile_snapshot_digest"
|
|
) REFERENCES "knowledge_space_profile_revisions" (
|
|
"tenant_id", "knowledge_space_id", "kind", "id", "revision", "snapshot_digest"
|
|
) ON DELETE RESTRICT,
|
|
FOREIGN KEY (
|
|
"tenant_id", "knowledge_space_id", "base_retrieval_profile_kind",
|
|
"base_retrieval_profile_revision_id", "base_retrieval_profile_revision",
|
|
"base_retrieval_profile_snapshot_digest"
|
|
) REFERENCES "knowledge_space_profile_revisions" (
|
|
"tenant_id", "knowledge_space_id", "kind", "id", "revision", "snapshot_digest"
|
|
) ON DELETE RESTRICT,
|
|
FOREIGN KEY (
|
|
"tenant_id", "knowledge_space_id", "base_publication_id", "base_publication_fingerprint"
|
|
) REFERENCES "projection_set_publications" (
|
|
"tenant_id", "knowledge_space_id", "id", "fingerprint"
|
|
) ON DELETE RESTRICT,
|
|
FOREIGN KEY (
|
|
"tenant_id", "knowledge_space_id", "candidate_publication_id",
|
|
"candidate_publication_fingerprint"
|
|
) REFERENCES "projection_set_publications" (
|
|
"tenant_id", "knowledge_space_id", "id", "fingerprint"
|
|
) ON DELETE RESTRICT,
|
|
FOREIGN KEY (
|
|
"tenant_id", "knowledge_space_id", "permission_snapshot_id",
|
|
"requested_by_subject_id", "access_channel"
|
|
)
|
|
REFERENCES "knowledge_space_permission_snapshots" (
|
|
"tenant_id", "knowledge_space_id", "id", "subject_id", "access_channel"
|
|
) ON DELETE RESTRICT
|
|
);
|
|
|
|
-- Recover a table left by an earlier attempt that failed while creating the oversized composite
|
|
-- key. The original tuple remains stored and is compared after digest lookup for collision safety.
|
|
ALTER TABLE "knowledge_space_profile_migration_runs"
|
|
ADD COLUMN IF NOT EXISTS "idempotency_digest" CHAR(64);
|
|
UPDATE "knowledge_space_profile_migration_runs"
|
|
SET "idempotency_digest" = encode(sha256(convert_to(
|
|
'v1|'
|
|
|| octet_length("tenant_id")::text || ':' || "tenant_id" || '|'
|
|
|| octet_length("knowledge_space_id"::text)::text || ':' || "knowledge_space_id"::text || '|'
|
|
|| octet_length("requested_by_subject_id")::text || ':' || "requested_by_subject_id" || '|'
|
|
|| octet_length("idempotency_key")::text || ':' || "idempotency_key" || '|',
|
|
'UTF8'
|
|
)), 'hex')
|
|
WHERE "idempotency_digest" IS NULL;
|
|
ALTER TABLE "knowledge_space_profile_migration_runs"
|
|
ALTER COLUMN "idempotency_digest" SET NOT NULL;
|
|
|
|
DROP INDEX IF EXISTS "knowledge_space_profile_migration_runs_idempotency_uq";
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "knowledge_space_profile_migration_runs_idempotency_digest_uq"
|
|
ON "knowledge_space_profile_migration_runs" ("idempotency_digest");
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "knowledge_space_profile_migration_runs_active_uq"
|
|
ON "knowledge_space_profile_migration_runs" (
|
|
"tenant_id", "knowledge_space_id", "active_slot"
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "knowledge_space_profile_migration_runs_claim_idx"
|
|
ON "knowledge_space_profile_migration_runs" (
|
|
"run_state", "lease_expires_at", "updated_at", "id"
|
|
);
|
|
CREATE INDEX IF NOT EXISTS "knowledge_space_profile_migration_runs_space_idx"
|
|
ON "knowledge_space_profile_migration_runs" (
|
|
"tenant_id", "knowledge_space_id", "created_at", "id"
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS "knowledge_space_profile_migration_outbox" (
|
|
"id" UUID PRIMARY KEY NOT NULL,
|
|
"run_id" UUID NOT NULL,
|
|
"delivery_revision" INTEGER NOT NULL,
|
|
"status" VARCHAR(16) NOT NULL,
|
|
"available_at" TIMESTAMPTZ NOT NULL,
|
|
"locked_by" VARCHAR(255),
|
|
"lock_token" UUID,
|
|
"locked_until" TIMESTAMPTZ,
|
|
"last_error" TEXT,
|
|
"created_at" TIMESTAMPTZ NOT NULL,
|
|
"updated_at" TIMESTAMPTZ NOT NULL,
|
|
"delivered_at" TIMESTAMPTZ,
|
|
CONSTRAINT "knowledge_space_profile_migration_outbox_state_ck"
|
|
CHECK ("status" IN ('pending', 'leased', 'completed', 'canceled')),
|
|
CONSTRAINT "knowledge_space_profile_migration_outbox_positive_ck"
|
|
CHECK ("delivery_revision" >= 1),
|
|
CONSTRAINT "knowledge_space_profile_migration_outbox_lock_ck"
|
|
CHECK (
|
|
("status" = 'leased' AND "locked_by" IS NOT NULL AND "lock_token" IS NOT NULL
|
|
AND "locked_until" IS NOT NULL)
|
|
OR ("status" <> 'leased' AND "locked_by" IS NULL AND "lock_token" IS NULL
|
|
AND "locked_until" IS NULL)
|
|
),
|
|
CONSTRAINT "knowledge_space_profile_migration_outbox_lock_token_ck"
|
|
CHECK (
|
|
"lock_token" IS NULL
|
|
OR "lock_token" <> '00000000-0000-0000-0000-000000000000'::uuid
|
|
),
|
|
FOREIGN KEY ("run_id")
|
|
REFERENCES "knowledge_space_profile_migration_runs" ("id") ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "knowledge_space_profile_migration_outbox_delivery_uq"
|
|
ON "knowledge_space_profile_migration_outbox" ("run_id", "delivery_revision");
|
|
CREATE INDEX IF NOT EXISTS "knowledge_space_profile_migration_outbox_claim_idx"
|
|
ON "knowledge_space_profile_migration_outbox" (
|
|
"status", "available_at", "locked_until", "id"
|
|
);
|