fix: fix migrations
This commit is contained in:
@@ -17,8 +17,8 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
for column in cron::Column::iter() {
|
||||
if matches!(
|
||||
column,
|
||||
cron::Column::SubscriberTask
|
||||
| cron::Column::SystemTask
|
||||
cron::Column::SubscriberTaskCron
|
||||
| cron::Column::SystemTaskCron
|
||||
| cron::Column::CronExpr
|
||||
| cron::Column::Enabled
|
||||
| cron::Column::TimeoutMs
|
||||
@@ -45,8 +45,11 @@ fn skip_columns_for_entity_input(context: &mut BuilderContext) {
|
||||
pub fn register_cron_to_schema_context(context: &mut BuilderContext) {
|
||||
restrict_subscriber_for_entity::<cron::Entity>(context, &cron::Column::SubscriberId);
|
||||
|
||||
restrict_subscriber_tasks_for_entity::<cron::Entity>(context, &cron::Column::SubscriberTask);
|
||||
restrict_system_tasks_for_entity::<cron::Entity>(context, &cron::Column::SystemTask);
|
||||
restrict_subscriber_tasks_for_entity::<cron::Entity>(
|
||||
context,
|
||||
&cron::Column::SubscriberTaskCron,
|
||||
);
|
||||
restrict_system_tasks_for_entity::<cron::Entity>(context, &cron::Column::SystemTaskCron);
|
||||
skip_columns_for_entity_input(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ use sea_orm::{
|
||||
QuerySelect, QueryTrait, prelude::Expr, sea_query::Query,
|
||||
};
|
||||
use seaography::{
|
||||
Builder as SeaographyBuilder, BuilderContext, SeaographyError, prepare_active_model,
|
||||
Builder as SeaographyBuilder, BuilderContext, GuardAction, SeaographyError,
|
||||
prepare_active_model,
|
||||
};
|
||||
use ts_rs::TS;
|
||||
|
||||
@@ -59,6 +60,14 @@ where
|
||||
restrict_jsonb_filter_input_for_entity::<T>(context, column);
|
||||
convert_jsonb_output_for_entity::<T>(context, column, Some(Case::Camel));
|
||||
let entity_column_name = get_entity_and_column_name::<T>(context, column);
|
||||
context.guards.field_guards.insert(
|
||||
entity_column_name.clone(),
|
||||
Box::new(|_resolver_ctx| {
|
||||
GuardAction::Block(Some(
|
||||
"SystemTask can not be created by subscribers now".to_string(),
|
||||
))
|
||||
}),
|
||||
);
|
||||
|
||||
context.types.input_type_overwrites.insert(
|
||||
entity_column_name.clone(),
|
||||
@@ -112,6 +121,7 @@ pub fn register_system_tasks_to_schema_builder(
|
||||
.description(system_tasks::SystemTask::decl()),
|
||||
);
|
||||
builder.register_enumeration::<system_tasks::SystemTaskType>();
|
||||
builder.register_enumeration::<system_tasks::SystemTaskStatus>();
|
||||
|
||||
builder = register_entity_default_readonly!(builder, system_tasks);
|
||||
let builder_context = builder.context;
|
||||
|
||||
@@ -189,8 +189,8 @@ pub enum Cron {
|
||||
MaxAttempts,
|
||||
Priority,
|
||||
Status,
|
||||
SubscriberTask,
|
||||
SystemTask,
|
||||
SubscriberTaskCron,
|
||||
SystemTaskCron,
|
||||
}
|
||||
|
||||
#[derive(sea_query::Iden)]
|
||||
@@ -317,6 +317,26 @@ pub trait CustomSchemaManagerExt {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_foreign_key_if_not_exists<
|
||||
T: IntoIden + 'static + Send,
|
||||
S: IntoIden + 'static + Send,
|
||||
>(
|
||||
&self,
|
||||
from_tbl: T,
|
||||
foreign_key: S,
|
||||
stmt: ForeignKeyCreateStatement,
|
||||
) -> Result<(), DbErr>;
|
||||
|
||||
async fn drop_foreign_key_if_exists<
|
||||
T: IntoIden + 'static + Send,
|
||||
S: IntoIden + 'static + Send,
|
||||
>(
|
||||
&self,
|
||||
from_tbl: T,
|
||||
foreign_key: S,
|
||||
stmt: ForeignKeyDropStatement,
|
||||
) -> Result<(), DbErr>;
|
||||
|
||||
async fn create_postgres_enum_for_active_enum<
|
||||
E: IntoTypeRef + IntoIden + Send + Clone,
|
||||
I: IntoIterator<Item = String> + Send,
|
||||
@@ -403,6 +423,71 @@ impl CustomSchemaManagerExt for SchemaManager<'_> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_foreign_key_if_not_exists<
|
||||
T: IntoIden + 'static + Send,
|
||||
S: IntoIden + 'static + Send,
|
||||
>(
|
||||
&self,
|
||||
from_tbl: T,
|
||||
foreign_key: S,
|
||||
stmt: ForeignKeyCreateStatement,
|
||||
) -> Result<(), DbErr> {
|
||||
let from_tbl = from_tbl.into_iden().to_string();
|
||||
let foreign_key = foreign_key.into_iden().to_string();
|
||||
let db = self
|
||||
.get_connection()
|
||||
.query_one(Statement::from_string(
|
||||
self.get_database_backend(),
|
||||
format!(
|
||||
"
|
||||
SELECT CONSTRAINT_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_NAME = '{from_tbl}' AND CONSTRAINT_NAME = '{foreign_key}'
|
||||
"
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
|
||||
if db.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.create_foreign_key(stmt).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn drop_foreign_key_if_exists<
|
||||
T: IntoIden + 'static + Send,
|
||||
S: IntoIden + 'static + Send,
|
||||
>(
|
||||
&self,
|
||||
from_tbl: T,
|
||||
foreign_key: S,
|
||||
stmt: ForeignKeyDropStatement,
|
||||
) -> Result<(), DbErr> {
|
||||
let from_tbl = from_tbl.into_iden().to_string();
|
||||
let foreign_key = foreign_key.into_iden().to_string();
|
||||
let db = self
|
||||
.get_connection()
|
||||
.query_one(Statement::from_string(
|
||||
self.get_database_backend(),
|
||||
format!(
|
||||
"
|
||||
SELECT CONSTRAINT_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_NAME = '{from_tbl}' AND CONSTRAINT_NAME = '{foreign_key}'
|
||||
"
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
|
||||
if db.is_some() {
|
||||
self.drop_foreign_key(stmt).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_postgres_enum_for_active_enum<
|
||||
E: IntoTypeRef + IntoIden + Send + Clone,
|
||||
I: IntoIterator<Item = String> + Send,
|
||||
|
||||
@@ -90,6 +90,11 @@ impl MigrationTrait for Migration {
|
||||
SimpleExpr::from(AuthType::Basic).as_enum(AuthTypeEnum),
|
||||
seed_subscriber_id.into(),
|
||||
])
|
||||
.on_conflict(
|
||||
OnConflict::columns([Auth::Pid, Auth::AuthType])
|
||||
.do_nothing()
|
||||
.to_owned(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -72,16 +72,22 @@ impl MigrationTrait for Migration {
|
||||
Table::alter()
|
||||
.table(Subscriptions::Table)
|
||||
.add_column_if_not_exists(integer_null(Subscriptions::CredentialId))
|
||||
.add_foreign_key(
|
||||
TableForeignKey::new()
|
||||
.name("fk_subscriptions_credential_id")
|
||||
.from_tbl(Subscriptions::Table)
|
||||
.from_col(Subscriptions::CredentialId)
|
||||
.to_tbl(Credential3rd::Table)
|
||||
.to_col(Credential3rd::Id)
|
||||
.on_update(ForeignKeyAction::Cascade)
|
||||
.on_delete(ForeignKeyAction::SetNull),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_foreign_key_if_not_exists(
|
||||
Subscriptions::Table,
|
||||
"fk_subscriptions_credential_id",
|
||||
ForeignKeyCreateStatement::new()
|
||||
.name("fk_subscriptions_credential_id")
|
||||
.from_tbl(Subscriptions::Table)
|
||||
.from_col(Subscriptions::CredentialId)
|
||||
.to_tbl(Credential3rd::Table)
|
||||
.to_col(Credential3rd::Id)
|
||||
.on_update(ForeignKeyAction::Cascade)
|
||||
.on_delete(ForeignKeyAction::SetNull)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -23,7 +23,7 @@ impl MigrationTrait for Migration {
|
||||
.table((ApalisSchema::Schema, ApalisJobs::Table))
|
||||
.add_column_if_not_exists(integer_null(ApalisJobs::SubscriberId))
|
||||
.add_column_if_not_exists(integer_null(ApalisJobs::SubscriptionId))
|
||||
.add_column_if_not_exists(string_null(ApalisJobs::TaskType))
|
||||
.add_column_if_not_exists(text_null(ApalisJobs::TaskType))
|
||||
.add_foreign_key(
|
||||
TableForeignKey::new()
|
||||
.name("fk_apalis_jobs_subscriber_id")
|
||||
|
||||
@@ -56,8 +56,8 @@ impl MigrationTrait for Migration {
|
||||
CronStatusEnum,
|
||||
CronStatus::iden_values(),
|
||||
))
|
||||
.col(json_binary_null(Cron::SubscriberTask))
|
||||
.col(json_binary_null(Cron::SystemTask))
|
||||
.col(json_binary_null(Cron::SubscriberTaskCron))
|
||||
.col(json_binary_null(Cron::SystemTaskCron))
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("fk_cron_subscriber_id")
|
||||
@@ -102,25 +102,25 @@ impl MigrationTrait for Migration {
|
||||
new_subscriber_task_subscription_id integer;
|
||||
new_system_task_subscriber_id integer;
|
||||
BEGIN
|
||||
new_subscriber_task_subscriber_id = (NEW.{subscriber_task} ->> 'subscriber_id')::integer;
|
||||
new_subscriber_task_subscription_id = (NEW.{subscriber_task} ->> 'subscription_id')::integer;
|
||||
new_system_task_subscriber_id = (NEW.{system_task} ->> 'subscriber_id')::integer;
|
||||
IF new_subscriber_task_subscriber_id != (OLD.{subscriber_task} ->> 'subscriber_id')::integer AND new_subscriber_task_subscriber_id != NEW.{subscriber_id} THEN
|
||||
new_subscriber_task_subscriber_id = (NEW.{subscriber_task_cron} ->> 'subscriber_id')::integer;
|
||||
new_subscriber_task_subscription_id = (NEW.{subscriber_task_cron} ->> 'subscription_id')::integer;
|
||||
new_system_task_subscriber_id = (NEW.{system_task_cron} ->> 'subscriber_id')::integer;
|
||||
IF new_subscriber_task_subscriber_id != (OLD.{subscriber_task_cron} ->> 'subscriber_id')::integer AND new_subscriber_task_subscriber_id != NEW.{subscriber_id} THEN
|
||||
NEW.{subscriber_id} = new_subscriber_task_subscriber_id;
|
||||
END IF;
|
||||
IF new_subscriber_task_subscription_id != (OLD.{subscriber_task} ->> 'subscription_id')::integer AND new_subscriber_task_subscription_id != NEW.{subscription_id} THEN
|
||||
IF new_subscriber_task_subscription_id != (OLD.{subscriber_task_cron} ->> 'subscription_id')::integer AND new_subscriber_task_subscription_id != NEW.{subscription_id} THEN
|
||||
NEW.{subscription_id} = new_subscriber_task_subscription_id;
|
||||
END IF;
|
||||
IF new_system_task_subscriber_id != (OLD.{system_task} ->> 'subscriber_id')::integer AND new_system_task_subscriber_id != NEW.{subscriber_id} THEN
|
||||
IF new_system_task_subscriber_id != (OLD.{system_task_cron} ->> 'subscriber_id')::integer AND new_system_task_subscriber_id != NEW.{subscriber_id} THEN
|
||||
NEW.{subscriber_id} = new_system_task_subscriber_id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;"#,
|
||||
subscriber_task = &Cron::SubscriberTask.to_string(),
|
||||
subscriber_task_cron = &Cron::SubscriberTaskCron.to_string(),
|
||||
subscriber_id = &Cron::SubscriberId.to_string(),
|
||||
subscription_id = &Cron::SubscriptionId.to_string(),
|
||||
system_task = &Cron::SystemTask.to_string(),
|
||||
system_task_cron = &Cron::SystemTaskCron.to_string(),
|
||||
)).await?;
|
||||
|
||||
db.execute_unprepared(&format!(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
mod core;
|
||||
mod registry;
|
||||
|
||||
pub use core::{
|
||||
CHECK_AND_TRIGGER_DUE_CRONS_FUNCTION_NAME, CRON_DUE_EVENT,
|
||||
@@ -71,8 +70,8 @@ pub struct Model {
|
||||
pub status: CronStatus,
|
||||
#[sea_orm(default_expr = "true")]
|
||||
pub enabled: bool,
|
||||
pub subscriber_task: Option<subscriber_tasks::SubscriberTask>,
|
||||
pub system_task: Option<system_tasks::SystemTask>,
|
||||
pub subscriber_task_cron: Option<subscriber_tasks::SubscriberTask>,
|
||||
pub system_task_cron: Option<system_tasks::SystemTask>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
@@ -152,19 +151,19 @@ impl ActiveModelBehavior for ActiveModel {
|
||||
self.next_run = Set(Some(next_run));
|
||||
}
|
||||
if let ActiveValue::Set(Some(subscriber_id)) = self.subscriber_id
|
||||
&& let ActiveValue::Set(Some(ref subscriber_task)) = self.subscriber_task
|
||||
&& let ActiveValue::Set(Some(ref subscriber_task)) = self.subscriber_task_cron
|
||||
&& subscriber_task.get_subscriber_id() != subscriber_id
|
||||
{
|
||||
return Err(DbErr::Custom(
|
||||
"Cron subscriber_id does not match subscriber_task.subscriber_id".to_string(),
|
||||
"Cron subscriber_id does not match subscriber_task_cron.subscriber_id".to_string(),
|
||||
));
|
||||
}
|
||||
if let ActiveValue::Set(Some(subscriber_id)) = self.subscriber_id
|
||||
&& let ActiveValue::Set(Some(ref system_task)) = self.system_task
|
||||
&& let ActiveValue::Set(Some(ref system_task)) = self.system_task_cron
|
||||
&& system_task.get_subscriber_id() != Some(subscriber_id)
|
||||
{
|
||||
return Err(DbErr::Custom(
|
||||
"Cron subscriber_id does not match system_task.subscriber_id".to_string(),
|
||||
"Cron subscriber_id does not match system_task_cron.subscriber_id".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -248,14 +247,14 @@ impl Model {
|
||||
}
|
||||
|
||||
async fn exec_cron(&self, ctx: &dyn AppContextTrait) -> RecorderResult<()> {
|
||||
if let Some(subscriber_task) = self.subscriber_task.as_ref() {
|
||||
if let Some(subscriber_task) = self.subscriber_task_cron.as_ref() {
|
||||
let task_service = ctx.task();
|
||||
let mut new_subscriber_task = subscriber_task.clone();
|
||||
new_subscriber_task.set_cron_id(Some(self.id));
|
||||
task_service
|
||||
.add_subscriber_task(new_subscriber_task)
|
||||
.await?;
|
||||
} else if let Some(system_task) = self.system_task.as_ref() {
|
||||
} else if let Some(system_task) = self.system_task_cron.as_ref() {
|
||||
let task_service = ctx.task();
|
||||
let mut new_system_task = system_task.clone();
|
||||
new_system_task.set_cron_id(Some(self.id));
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -302,7 +302,10 @@ mod tests {
|
||||
use tracing::Level;
|
||||
|
||||
use super::*;
|
||||
use crate::test_utils::{app::TestingPreset, tracing::try_init_testing_tracing};
|
||||
use crate::test_utils::{
|
||||
// app::TestingPreset,
|
||||
tracing::try_init_testing_tracing,
|
||||
};
|
||||
|
||||
#[fixture]
|
||||
fn before_each() {
|
||||
@@ -312,13 +315,6 @@ mod tests {
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_cron_due_listening(before_each: ()) -> RecorderResult<()> {
|
||||
let mut preset = TestingPreset::default().await?;
|
||||
let app_ctx = preset.app_ctx.clone();
|
||||
|
||||
let db = app_ctx.db();
|
||||
|
||||
todo!();
|
||||
|
||||
Ok(())
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user