@@ -4,12 +4,14 @@ use actix_web::{
4
4
post,
5
5
web:: { Data , Json , Path } ,
6
6
} ;
7
+ use chrono:: Utc ;
7
8
use etl_config:: shared:: { ReplicatorConfig , SupabaseConfig , TlsConfig } ;
8
9
use etl_postgres:: replication:: { TableLookupError , get_table_name_from_oid, health, state} ;
9
10
use etl_postgres:: schema:: TableId ;
10
11
use secrecy:: ExposeSecret ;
11
12
use serde:: { Deserialize , Serialize } ;
12
13
use sqlx:: { PgPool , PgTransaction } ;
14
+ use std:: collections:: BTreeMap ;
13
15
use std:: ops:: DerefMut ;
14
16
use thiserror:: Error ;
15
17
use utoipa:: ToSchema ;
@@ -24,8 +26,8 @@ use crate::db::images::{Image, ImagesDbError};
24
26
use crate :: db:: pipelines:: { Pipeline , PipelinesDbError } ;
25
27
use crate :: db:: replicators:: { Replicator , ReplicatorsDbError } ;
26
28
use crate :: db:: sources:: { Source , SourcesDbError , source_exists} ;
27
- use crate :: k8s_client:: TRUSTED_ROOT_CERT_KEY_NAME ;
28
29
use crate :: k8s_client:: { K8sClient , K8sError , PodPhase , TRUSTED_ROOT_CERT_CONFIG_MAP_NAME } ;
30
+ use crate :: k8s_client:: { RESTARTED_AT_ANNOTATION_KEY , TRUSTED_ROOT_CERT_KEY_NAME } ;
29
31
use crate :: routes:: {
30
32
ErrorMessage , TenantIdError , connect_to_source_database_with_defaults, extract_tenant_id,
31
33
} ;
@@ -360,7 +362,6 @@ pub enum PipelineStatus {
360
362
Stopped ,
361
363
Starting ,
362
364
Started ,
363
- Stopping ,
364
365
Unknown ,
365
366
Failed ,
366
367
}
@@ -1088,7 +1089,7 @@ pub async fn update_pipeline_config(
1088
1089
Ok ( Json ( response) )
1089
1090
}
1090
1091
1091
- #[ derive( Debug , Serialize , Deserialize ) ]
1092
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
1092
1093
struct Secrets {
1093
1094
postgres_password : String ,
1094
1095
big_query_service_account_key : Option < String > ,
@@ -1107,7 +1108,7 @@ async fn create_or_update_pipeline_in_k8s(
1107
1108
1108
1109
// We create the secrets.
1109
1110
let secrets = build_secrets ( & source. config , & destination. config ) ;
1110
- create_or_update_secrets ( k8s_client, & prefix, secrets) . await ?;
1111
+ create_or_update_secrets ( k8s_client, & prefix, secrets. clone ( ) ) . await ?;
1111
1112
1112
1113
// We create the replicator configuration.
1113
1114
let replicator_config = build_replicator_config (
@@ -1120,14 +1121,31 @@ async fn create_or_update_pipeline_in_k8s(
1120
1121
} ,
1121
1122
)
1122
1123
. await ?;
1123
- create_or_update_config ( k8s_client, & prefix, replicator_config) . await ?;
1124
+ create_or_update_config ( k8s_client, & prefix, replicator_config. clone ( ) ) . await ?;
1125
+
1126
+ // To force restart everytime, we want to annotate the stateful set with the current UTC time for every
1127
+ // start call. Technically we can optimally perform a restart by calculating a checksum on a deterministic
1128
+ // set of inputs like the configs, states in the database, etc... however we deemed that too cumbersome
1129
+ // and risky, since forgetting a component will lead to the pipeline not restarting.
1130
+ let mut annotations = BTreeMap :: new ( ) ;
1131
+ annotations. insert (
1132
+ RESTARTED_AT_ANNOTATION_KEY . to_string ( ) ,
1133
+ get_restarted_at_annotation_value ( ) ,
1134
+ ) ;
1124
1135
1125
1136
// We create the replicator stateful set.
1126
- create_or_update_replicator ( k8s_client, & prefix, image. name ) . await ?;
1137
+ create_or_update_replicator ( k8s_client, & prefix, image. name , Some ( annotations ) ) . await ?;
1127
1138
1128
1139
Ok ( ( ) )
1129
1140
}
1130
1141
1142
+ fn get_restarted_at_annotation_value ( ) -> String {
1143
+ let now = Utc :: now ( ) ;
1144
+ // We use nanoseconds to decrease the likelihood of generating the same annotation in sequence,
1145
+ // which would not result in a restart.
1146
+ now. to_rfc3339_opts ( chrono:: SecondsFormat :: Nanos , true )
1147
+ }
1148
+
1131
1149
async fn delete_pipeline_in_k8s (
1132
1150
k8s_client : & dyn K8sClient ,
1133
1151
tenant_id : & str ,
@@ -1281,9 +1299,10 @@ async fn create_or_update_replicator(
1281
1299
k8s_client : & dyn K8sClient ,
1282
1300
prefix : & str ,
1283
1301
replicator_image : String ,
1302
+ template_annotations : Option < BTreeMap < String , String > > ,
1284
1303
) -> Result < ( ) , PipelineError > {
1285
1304
k8s_client
1286
- . create_or_update_stateful_set ( prefix, & replicator_image)
1305
+ . create_or_update_stateful_set ( prefix, & replicator_image, template_annotations )
1287
1306
. await ?;
1288
1307
1289
1308
Ok ( ( ) )
0 commit comments