Replace Flyway schema setup with JPA mappings
This commit is contained in:
parent
e71ba9c290
commit
8d6ddfecfb
8
pom.xml
8
pom.xml
|
|
@ -103,14 +103,6 @@
|
|||
<artifactId>postgresql</artifactId>
|
||||
<version>42.7.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-flyway</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-database-postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ until docker exec "$POSTGRES_CONTAINER" pg_isready -U "$POSTGRES_USER" -d "$POST
|
|||
sleep 1
|
||||
done
|
||||
|
||||
# Il database è usa-e-getta: crea lo schema dalle entity e non applica le
|
||||
# migration Flyway, che richiedono uno schema base già esistente.
|
||||
# Il database è usa-e-getta: crea lo schema direttamente dalle entity.
|
||||
./mvnw spring-boot:run \
|
||||
-Dspring-boot.run.jvmArguments="-Dddl-auto=create-drop -Dspring.flyway.enabled=false"
|
||||
-Dspring-boot.run.jvmArguments="-Dddl-auto=create-drop"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import lombok.AllArgsConstructor;
|
|||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
@Entity
|
||||
@Table(name = "bias_impact_job_entity", indexes = {
|
||||
|
|
@ -44,11 +45,13 @@ public class BiasImpactJobEntity {
|
|||
private String stepId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
private BiasImpactJobKind kind;
|
||||
@Column(nullable = false, length = 32)
|
||||
@ColumnDefault("'ISOLATED_STEP'")
|
||||
@Builder.Default
|
||||
private BiasImpactJobKind kind = BiasImpactJobKind.ISOLATED_STEP;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = false, length = 32)
|
||||
private BiasImpactJobStatus status;
|
||||
|
||||
@Column(name = "created_at", nullable = false)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import lombok.AllArgsConstructor;
|
|||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
@Entity
|
||||
@Table(name = "bias_impact_report_entity", indexes = {
|
||||
|
|
@ -35,6 +36,7 @@ public class BiasImpactReportEntity {
|
|||
private String id;
|
||||
|
||||
@NotBlank
|
||||
@Column(nullable = false)
|
||||
private String owner;
|
||||
|
||||
@NotBlank
|
||||
|
|
@ -48,8 +50,10 @@ public class BiasImpactReportEntity {
|
|||
@Column(name = "created_at", nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Builder.Default
|
||||
@Column(name = "raw_outputs_included", nullable = false)
|
||||
private boolean rawOutputsIncluded;
|
||||
@ColumnDefault("true")
|
||||
private boolean rawOutputsIncluded = true;
|
||||
|
||||
@Column(name = "report_data", columnDefinition = "TEXT")
|
||||
@Convert(converter = BiasImpactReportConverter.class)
|
||||
|
|
@ -66,5 +70,6 @@ public class BiasImpactReportEntity {
|
|||
*/
|
||||
@Version
|
||||
@Column(name = "version", nullable = false)
|
||||
@ColumnDefault("0")
|
||||
private long version;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,14 +11,29 @@ import jakarta.persistence.Convert;
|
|||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
@Entity
|
||||
@Table(indexes = {
|
||||
@Index(name = "idx_execution_owner_kind", columnList = "owner, execution_kind"),
|
||||
@Index(name = "idx_execution_parent", columnList = "parent_execution_id, parent_step_id, parent_iteration_index"),
|
||||
@Index(name = "idx_execution_project_run", columnList = "owner, project_run_id"),
|
||||
@Index(name = "idx_execution_owner_project", columnList = "owner, project_id")
|
||||
})
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
|
|
@ -60,10 +75,22 @@ public class ExecutionEntity {
|
|||
@Builder.Default
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false, length = 32)
|
||||
@ColumnDefault("'TOP_LEVEL'")
|
||||
private ExecutionKind executionKind = ExecutionKind.TOP_LEVEL;
|
||||
|
||||
@Column(name = "parent_execution_id")
|
||||
private String parentExecutionId;
|
||||
|
||||
/**
|
||||
* Schema-only association for the self-referencing foreign key. The service continues to use
|
||||
* {@link #parentExecutionId}, so this association is deliberately read-only.
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "parent_execution_id", insertable = false, updatable = false,
|
||||
foreignKey = @ForeignKey(name = "fk_execution_parent"))
|
||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||
private ExecutionEntity parentExecution;
|
||||
|
||||
private String parentStepId;
|
||||
|
||||
private Integer parentIterationIndex;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import jakarta.persistence.Entity;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
|
@ -18,6 +20,7 @@ import lombok.Data;
|
|||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Table(indexes = @Index(name = "idx_flow_owner_project", columnList = "owner, project_id"))
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import jakarta.persistence.Entity;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
|
@ -19,7 +20,7 @@ import lombok.NoArgsConstructor;
|
|||
|
||||
@Entity
|
||||
@Table(name = "project", uniqueConstraints = @UniqueConstraint(name = "uk_project_owner_name",
|
||||
columnNames = { "owner", "name" }))
|
||||
columnNames = { "owner", "name" }), indexes = @Index(name = "idx_project_owner", columnList = "owner"))
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
|
|
|
|||
|
|
@ -7,16 +7,19 @@ import jakarta.persistence.Entity;
|
|||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_secret", uniqueConstraints = @UniqueConstraint(name = "uk_user_secret_owner_label",
|
||||
columnNames = { "owner", "label" }))
|
||||
columnNames = { "owner", "label" }), indexes = @Index(name = "idx_user_secret_owner_provider_active",
|
||||
columnList = "owner, provider, active"))
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
|
|
@ -30,10 +33,10 @@ public class UserSecretEntity {
|
|||
@Column(nullable = false)
|
||||
private String owner;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = false, length = 120)
|
||||
private String label;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = false, length = 120)
|
||||
private String provider;
|
||||
|
||||
@Column(length = 1000)
|
||||
|
|
@ -45,7 +48,7 @@ public class UserSecretEntity {
|
|||
@Column(nullable = false)
|
||||
private String iv;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = false, length = 64)
|
||||
private String algorithm;
|
||||
|
||||
@Column(nullable = false)
|
||||
|
|
@ -58,5 +61,6 @@ public class UserSecretEntity {
|
|||
|
||||
@Builder.Default
|
||||
@Column(nullable = false)
|
||||
@ColumnDefault("true")
|
||||
private boolean active = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ spring.datasource.password=${DB_PASSWORD:password}
|
|||
spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
|
||||
spring.jpa.hibernate.ddl-auto=${ddl-auto:validate}
|
||||
spring.flyway.baseline-on-migrate=${FLYWAY_BASELINE_ON_MIGRATE:true}
|
||||
spring.flyway.baseline-version=${FLYWAY_BASELINE_VERSION:1}
|
||||
|
||||
management.endpoints.web.exposure.include=health,info
|
||||
management.endpoint.health.show-details=always
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
-- Appending an LLM assessment to a report is a read-modify-write over its JSON, and the model calls
|
||||
-- in the middle take minutes. Two overlapping assessments both read a report with no history, and
|
||||
-- whichever saved last kept only its own: the other was silently gone. A version column is what lets
|
||||
-- the second writer be refused and retried against the row as it actually is.
|
||||
ALTER TABLE bias_impact_report_entity
|
||||
ADD COLUMN version BIGINT NOT NULL DEFAULT 0;
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
CREATE TABLE bias_impact_report_entity (
|
||||
id VARCHAR(255) PRIMARY KEY,
|
||||
owner VARCHAR(255) NOT NULL,
|
||||
baseline_execution_id VARCHAR(255) NOT NULL,
|
||||
biased_execution_id VARCHAR(255),
|
||||
created_at TIMESTAMP(6) NOT NULL,
|
||||
report_data TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX idx_bias_report_baseline_owner_created
|
||||
ON bias_impact_report_entity (baseline_execution_id, owner, created_at);
|
||||
|
||||
CREATE INDEX idx_bias_report_biased_execution
|
||||
ON bias_impact_report_entity (biased_execution_id);
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
ALTER TABLE bias_impact_report_entity
|
||||
ADD COLUMN raw_outputs_included BOOLEAN NOT NULL DEFAULT TRUE;
|
||||
|
||||
DELETE FROM bias_impact_report_entity
|
||||
WHERE biased_execution_id IS NOT NULL
|
||||
AND id IN (
|
||||
SELECT id
|
||||
FROM (
|
||||
SELECT id,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY baseline_execution_id, biased_execution_id, owner, raw_outputs_included
|
||||
ORDER BY created_at DESC, id DESC
|
||||
) AS duplicate_number
|
||||
FROM bias_impact_report_entity
|
||||
WHERE biased_execution_id IS NOT NULL
|
||||
) ranked_reports
|
||||
WHERE duplicate_number > 1
|
||||
);
|
||||
|
||||
ALTER TABLE bias_impact_report_entity
|
||||
ADD CONSTRAINT uk_bias_full_comparison
|
||||
UNIQUE (baseline_execution_id, biased_execution_id, owner, raw_outputs_included);
|
||||
|
||||
CREATE TABLE bias_impact_job_entity (
|
||||
id VARCHAR(255) PRIMARY KEY,
|
||||
owner VARCHAR(255) NOT NULL,
|
||||
execution_id VARCHAR(255) NOT NULL,
|
||||
step_id VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
created_at TIMESTAMP(6) NOT NULL,
|
||||
started_at TIMESTAMP(6),
|
||||
completed_at TIMESTAMP(6),
|
||||
report_id VARCHAR(255),
|
||||
error_code VARCHAR(255),
|
||||
error_message TEXT,
|
||||
request_data TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_bias_job_owner_created
|
||||
ON bias_impact_job_entity (owner, created_at);
|
||||
|
||||
CREATE INDEX idx_bias_job_status
|
||||
ON bias_impact_job_entity (status);
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
ALTER TABLE execution_entity
|
||||
ADD COLUMN execution_kind VARCHAR(32) NOT NULL DEFAULT 'TOP_LEVEL';
|
||||
|
||||
ALTER TABLE execution_entity
|
||||
ADD COLUMN parent_execution_id VARCHAR(255);
|
||||
|
||||
ALTER TABLE execution_entity
|
||||
ADD COLUMN parent_step_id VARCHAR(255);
|
||||
|
||||
ALTER TABLE execution_entity
|
||||
ADD COLUMN parent_iteration_index INTEGER;
|
||||
|
||||
ALTER TABLE execution_entity
|
||||
ADD COLUMN subflow_role VARCHAR(32);
|
||||
|
||||
ALTER TABLE execution_entity
|
||||
ADD CONSTRAINT fk_execution_parent
|
||||
FOREIGN KEY (parent_execution_id)
|
||||
REFERENCES execution_entity (id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
CREATE INDEX idx_execution_owner_kind
|
||||
ON execution_entity (owner, execution_kind);
|
||||
|
||||
CREATE INDEX idx_execution_parent
|
||||
ON execution_entity (parent_execution_id, parent_step_id, parent_iteration_index);
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
CREATE TABLE user_secret (
|
||||
id VARCHAR(255) PRIMARY KEY,
|
||||
owner VARCHAR(255) NOT NULL,
|
||||
label VARCHAR(120) NOT NULL,
|
||||
provider VARCHAR(120) NOT NULL,
|
||||
description VARCHAR(1000),
|
||||
ciphertext TEXT NOT NULL,
|
||||
iv VARCHAR(255) NOT NULL,
|
||||
algorithm VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP(6) NOT NULL,
|
||||
updated_at TIMESTAMP(6) NOT NULL,
|
||||
last_used_at TIMESTAMP(6),
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
CONSTRAINT uk_user_secret_owner_label UNIQUE (owner, label)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_user_secret_owner_provider_active
|
||||
ON user_secret (owner, provider, active);
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
CREATE TABLE project (
|
||||
id VARCHAR(255) PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description VARCHAR(1000),
|
||||
owner VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP(6) NOT NULL,
|
||||
last_update_at TIMESTAMP(6) NOT NULL,
|
||||
shared_context TEXT,
|
||||
CONSTRAINT uk_project_owner_name UNIQUE (owner, name)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_project_owner ON project (owner);
|
||||
|
||||
-- No foreign key on project_id, on purpose. The tests run on H2 with ddl-auto=create-drop and
|
||||
-- spring.flyway.enabled=false, and Hibernate's validate does not check foreign keys, so a
|
||||
-- constraint added here would exist only in production and never be exercised anywhere. The
|
||||
-- cascade is enforced in ProjectService, which deletes a project's flows before the project, and a
|
||||
-- dangling project_id degrades safely: the project name simply resolves to null.
|
||||
|
||||
-- project_order is unused for now: it is the stable display order a project run will need, and a
|
||||
-- nullable column costs nothing today while sparing an ALTER on flow_entity later.
|
||||
ALTER TABLE flow_entity ADD COLUMN project_id VARCHAR(255);
|
||||
ALTER TABLE flow_entity ADD COLUMN project_order INTEGER;
|
||||
|
||||
CREATE INDEX idx_flow_owner_project ON flow_entity (owner, project_id);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
-- Executions carry the project their source flow belonged to, plus the run that started them.
|
||||
--
|
||||
-- project_run_id is a new column rather than a reuse of run_group_id: that one means "the rerun
|
||||
-- history of one flow" (resolveHistoryGroupId keys off source_flow_id first, and run numbering
|
||||
-- depends on it), so overloading it would both fail to group a project run and corrupt per-flow
|
||||
-- rerun numbering.
|
||||
ALTER TABLE execution_entity ADD COLUMN project_id VARCHAR(255);
|
||||
ALTER TABLE execution_entity ADD COLUMN project_run_id VARCHAR(255);
|
||||
|
||||
CREATE INDEX idx_execution_project_run ON execution_entity (owner, project_run_id);
|
||||
CREATE INDEX idx_execution_owner_project ON execution_entity (owner, project_id);
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
-- Position of an execution inside its project run. A project run starts one flow at a time in this
|
||||
-- order, so the sequence has to survive a restart: it is the run's only state, deliberately, rather
|
||||
-- than a separate run table with a status machine to keep in sync with the executions themselves.
|
||||
ALTER TABLE execution_entity ADD COLUMN project_run_order INTEGER;
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
-- A bias job used to be one thing: re-run a step with the intervention active. Asking a model to
|
||||
-- assess an existing comparison is the second, and it reuses the same queue, recovery and polling
|
||||
-- rather than growing a parallel one - so the columns that only the first kind fills stop being
|
||||
-- mandatory.
|
||||
ALTER TABLE bias_impact_job_entity
|
||||
ADD COLUMN kind VARCHAR(32) NOT NULL DEFAULT 'ISOLATED_STEP';
|
||||
|
||||
ALTER TABLE bias_impact_job_entity
|
||||
ALTER COLUMN step_id DROP NOT NULL;
|
||||
|
||||
ALTER TABLE bias_impact_job_entity
|
||||
ALTER COLUMN request_data DROP NOT NULL;
|
||||
|
||||
ALTER TABLE bias_impact_job_entity
|
||||
ADD COLUMN report_target_id VARCHAR(255);
|
||||
|
||||
ALTER TABLE bias_impact_job_entity
|
||||
ADD COLUMN judge_data TEXT;
|
||||
|
|
@ -5,7 +5,6 @@ spring.datasource.password=
|
|||
# Use the native H2 dialect for schema generation while keeping MySQL compatibility mode.
|
||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||
spring.jpa.hibernate.ddl-auto=create-drop
|
||||
spring.flyway.enabled=false
|
||||
spring.jpa.properties.jakarta.persistence.validation.mode=none
|
||||
app.db.init.enabled=true
|
||||
app.assistant.default-model=assistant-test-model
|
||||
|
|
|
|||
Loading…
Reference in New Issue