refactor(scheduler): move scheduler to new crate to support workflows in multiple crates (#1681)

This commit is contained in:
Jagan
2023-09-06 13:11:09 +05:30
committed by GitHub
parent ec4652ec09
commit d4221f3368
72 changed files with 1966 additions and 1124 deletions

View File

@ -0,0 +1,132 @@
use common_utils::ext_traits::ValueExt;
use diesel_models::enums::{self as storage_enums};
use super::{ApiKeyExpiryWorkflow, ProcessTrackerWorkflow};
use crate::{
errors,
logger::error,
routes::AppState,
types::{
api,
storage::{self, ProcessTrackerExt},
},
utils::OptionExt,
};
#[async_trait::async_trait]
impl ProcessTrackerWorkflow for ApiKeyExpiryWorkflow {
async fn execute_workflow<'a>(
&'a self,
state: &'a AppState,
process: storage::ProcessTracker,
) -> Result<(), errors::ProcessTrackerError> {
let db = &*state.store;
let tracking_data: storage::ApiKeyExpiryWorkflow = process
.tracking_data
.clone()
.parse_value("ApiKeyExpiryWorkflow")?;
let key_store = state
.store
.get_merchant_key_store_by_merchant_id(
tracking_data.merchant_id.as_str(),
&state.store.get_master_key().to_vec().into(),
)
.await?;
let merchant_account = db
.find_merchant_account_by_merchant_id(tracking_data.merchant_id.as_str(), &key_store)
.await?;
let email_id = merchant_account
.merchant_details
.parse_value::<api::MerchantDetails>("MerchantDetails")?
.primary_email;
let task_id = process.id.clone();
let retry_count = process.retry_count;
let expires_in = tracking_data
.expiry_reminder_days
.get(
usize::try_from(retry_count)
.map_err(|_| errors::ProcessTrackerError::TypeConversionError)?,
)
.ok_or(errors::ProcessTrackerError::EApiErrorResponse(
errors::ApiErrorResponse::InvalidDataValue {
field_name: "index",
}
.into(),
))?;
state
.email_client
.clone()
.send_email(
email_id.ok_or_else(|| errors::ProcessTrackerError::MissingRequiredField)?,
"API Key Expiry Notice".to_string(),
format!("Dear Merchant,\n
It has come to our attention that your API key will expire in {expires_in} days. To ensure uninterrupted access to our platform and continued smooth operation of your services, we kindly request that you take the necessary actions as soon as possible.\n\n
Thanks,\n
Team Hyperswitch"),
)
.await
.map_err(|_| errors::ProcessTrackerError::FlowExecutionError {
flow: "ApiKeyExpiryWorkflow",
})?;
// If all the mails have been sent, then retry_count would be equal to length of the expiry_reminder_days vector
if retry_count
== i32::try_from(tracking_data.expiry_reminder_days.len() - 1)
.map_err(|_| errors::ProcessTrackerError::TypeConversionError)?
{
process
.finish_with_status(db, format!("COMPLETED_BY_PT_{task_id}"))
.await?
}
// If tasks are remaining that has to be scheduled
else {
let expiry_reminder_day = tracking_data
.expiry_reminder_days
.get(
usize::try_from(retry_count + 1)
.map_err(|_| errors::ProcessTrackerError::TypeConversionError)?,
)
.ok_or(errors::ProcessTrackerError::EApiErrorResponse(
errors::ApiErrorResponse::InvalidDataValue {
field_name: "index",
}
.into(),
))?;
let updated_schedule_time = tracking_data.api_key_expiry.map(|api_key_expiry| {
api_key_expiry.saturating_sub(time::Duration::days(i64::from(*expiry_reminder_day)))
});
let updated_process_tracker_data = storage::ProcessTrackerUpdate::Update {
name: None,
retry_count: Some(retry_count + 1),
schedule_time: updated_schedule_time,
tracking_data: None,
business_status: None,
status: Some(storage_enums::ProcessTrackerStatus::New),
updated_at: Some(common_utils::date_time::now()),
};
let task_ids = vec![task_id];
db.process_tracker_update_process_status_by_ids(task_ids, updated_process_tracker_data)
.await?;
}
Ok(())
}
async fn error_handler<'a>(
&'a self,
_state: &'a AppState,
process: storage::ProcessTracker,
_error: errors::ProcessTrackerError,
) -> errors::CustomResult<(), errors::ProcessTrackerError> {
error!(%process.id, "Failed while executing workflow");
Ok(())
}
}