Skip to content

Commit

Permalink
Merge branch 'main' into refunds-audit-log
Browse files Browse the repository at this point in the history
  • Loading branch information
harsh-sharma-juspay authored Feb 2, 2024
2 parents e869a45 + b2f4e61 commit dc31674
Show file tree
Hide file tree
Showing 28 changed files with 325 additions and 33 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ All notable changes to HyperSwitch will be documented here.

- - -

## 2024.02.02.0

### Features

- **configs:** [Noon] Add applepay mandate configs ([#3508](https://github.com/juspay/hyperswitch/pull/3508)) ([`7cf6c8c`](https://github.com/juspay/hyperswitch/commit/7cf6c8c0b9c4042f2e6b9277b7c75c85546821f7))
- Add deep health check for scheduler ([#3304](https://github.com/juspay/hyperswitch/pull/3304)) ([`170e10c`](https://github.com/juspay/hyperswitch/commit/170e10cb8e0880737585284dd43437f549c019d3))
- Add healthcheck for outgoing request ([#3519](https://github.com/juspay/hyperswitch/pull/3519)) ([`54fb61e`](https://github.com/juspay/hyperswitch/commit/54fb61eeebec503f599774fe9e97f6b6ce3f1458))

### Bug Fixes

- **core:** Fix mandate_details to store some value only if mandate_data struct is present ([#3525](https://github.com/juspay/hyperswitch/pull/3525)) ([`78fdad2`](https://github.com/juspay/hyperswitch/commit/78fdad218ca3ae3c7410dfb8a7a8a5e542adff1c))
- **logging:** Add an end log line for `LogSpanInitializer` ([#3528](https://github.com/juspay/hyperswitch/pull/3528)) ([`13be7e6`](https://github.com/juspay/hyperswitch/commit/13be7e6f8771a1128e3c0c5b189c91d9a0dd1416))

### Refactors

- **connector:** [CYBERSOURCE] Remove default case for Cybersource ([#2705](https://github.com/juspay/hyperswitch/pull/2705)) ([`1828ea6`](https://github.com/juspay/hyperswitch/commit/1828ea6187c46d9c18dc8a0b5224387403b998e2))

### Miscellaneous Tasks

- **postman:** Update Postman collection files ([`1deb37e`](https://github.com/juspay/hyperswitch/commit/1deb37ebd1128041ded64a4966a2d47a61e8c499))
- Add file storage config in env_specific toml ([#3512](https://github.com/juspay/hyperswitch/pull/3512)) ([`20efc30`](https://github.com/juspay/hyperswitch/commit/20efc3020ac389199eed13154f070685417ef82a))

**Full Changelog:** [`2024.02.01.0...2024.02.02.0`](https://github.com/juspay/hyperswitch/compare/2024.02.01.0...2024.02.02.0)

- - -

## 2024.02.01.0

### Features
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions config/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,12 @@ lower_fetch_limit = 1800 # Lower limit for fetching entries from redis
lock_key = "PRODUCER_LOCKING_KEY" # The following keys defines the producer lock that is created in redis with
lock_ttl = 160 # the ttl being the expiry (in seconds)

# Scheduler server configuration
[scheduler.server]
port = 3000 # Port on which the server will listen for incoming requests
host = "127.0.0.1" # Host IP address to bind the server to
workers = 1 # Number of actix workers to handle incoming requests concurrently

batch_size = 200 # Specifies the batch size the producer will push under a single entry in the redis queue

# Drainer configuration, which handles draining raw SQL queries from Redis streams to the SQL database
Expand Down Expand Up @@ -383,6 +389,7 @@ bank_debit.becs = { connector_list = "gocardless" } # Mandate supported payment
bank_debit.sepa = { connector_list = "gocardless" } # Mandate supported payment method type and connector for bank_debit
bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"} # Mandate supported payment method type and connector for bank_redirect
bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
wallet.apple_pay = { connector_list = "stripe,adyen,cybersource,noon" }


# Required fields info used while listing the payment_method_data
Expand Down
2 changes: 1 addition & 1 deletion config/deployments/integration_test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bank_debit.sepa.connector_list = "gocardless"
card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"
card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"
pay_later.klarna.connector_list = "adyen"
wallet.apple_pay.connector_list = "stripe,adyen,cybersource"
wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon"
wallet.google_pay.connector_list = "stripe,adyen,cybersource"
wallet.paypal.connector_list = "adyen"
bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
Expand Down
2 changes: 1 addition & 1 deletion config/deployments/production.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bank_debit.sepa.connector_list = "gocardless"
card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"
card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"
pay_later.klarna.connector_list = "adyen"
wallet.apple_pay.connector_list = "stripe,adyen,cybersource"
wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon"
wallet.google_pay.connector_list = "stripe,adyen,cybersource"
wallet.paypal.connector_list = "adyen"
bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
Expand Down
2 changes: 1 addition & 1 deletion config/deployments/sandbox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bank_debit.sepa.connector_list = "gocardless"
card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"
card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"
pay_later.klarna.connector_list = "adyen"
wallet.apple_pay.connector_list = "stripe,adyen,cybersource"
wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon"
wallet.google_pay.connector_list = "stripe,adyen,cybersource"
wallet.paypal.connector_list = "adyen"
bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
Expand Down
6 changes: 6 additions & 0 deletions config/deployments/scheduler/consumer.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ stream = "scheduler_stream"
[scheduler.consumer]
consumer_group = "scheduler_group"
disabled = false # This flag decides if the consumer should actively consume task

# Scheduler server configuration
[scheduler.server]
port = 3000 # Port on which the server will listen for incoming requests
host = "127.0.0.1" # Host IP address to bind the server to
workers = 1 # Number of actix workers to handle incoming requests concurrently
6 changes: 6 additions & 0 deletions config/deployments/scheduler/producer.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ lock_key = "producer_locking_key" # The following keys defines the producer lock
lock_ttl = 160 # the ttl being the expiry (in seconds)
lower_fetch_limit = 900 # Lower limit for fetching entries from redis queue (in seconds)
upper_fetch_limit = 0 # Upper limit for fetching entries from the redis queue (in seconds)0

# Scheduler server configuration
[scheduler.server]
port = 3000 # Port on which the server will listen for incoming requests
host = "127.0.0.1" # Host IP address to bind the server to
workers = 1 # Number of actix workers to handle incoming requests concurrently
5 changes: 5 additions & 0 deletions config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ stream = "SCHEDULER_STREAM"
disabled = false
consumer_group = "SCHEDULER_GROUP"

[scheduler.server]
port = 3000
host = "127.0.0.1"
workers = 1

[email]
sender_email = "[email protected]"
aws_region = ""
Expand Down
7 changes: 6 additions & 1 deletion config/docker_compose.toml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ stream = "SCHEDULER_STREAM"
disabled = false
consumer_group = "SCHEDULER_GROUP"

[scheduler.server]
port = 3000
host = "127.0.0.1"
workers = 1

#tokenization configuration which describe token lifetime and payment method for specific connector
[tokenization]
stripe = { long_lived_token = false, payment_method = "wallet", payment_method_type = { type = "disable_only", list = "google_pay" } }
Expand Down Expand Up @@ -334,7 +339,7 @@ adyen = { banks = "aib,bank_of_scotland,danske_bank,first_direct,first_trust,hal
[mandates.supported_payment_methods]
pay_later.klarna = {connector_list = "adyen"}
wallet.google_pay = {connector_list = "stripe,adyen"}
wallet.apple_pay = {connector_list = "stripe,adyen"}
wallet.apple_pay = {connector_list = "stripe,adyen,cybersource,noon"}
wallet.paypal = {connector_list = "adyen"}
card.credit = {connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"}
card.debit = {connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon"}
Expand Down
8 changes: 8 additions & 0 deletions crates/api_models/src/health_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ pub struct RouterHealthCheckResponse {
pub locker: bool,
#[cfg(feature = "olap")]
pub analytics: bool,
pub outgoing_request: bool,
}

impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SchedulerHealthCheckResponse {
pub database: bool,
pub redis: bool,
}

impl common_utils::events::ApiEventMetric for SchedulerHealthCheckResponse {}
125 changes: 123 additions & 2 deletions crates/router/src/bin/scheduler.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
#![recursion_limit = "256"]
use std::{str::FromStr, sync::Arc};

use actix_web::{dev::Server, web, Scope};
use api_models::health_check::SchedulerHealthCheckResponse;
use common_utils::ext_traits::{OptionExt, StringExt};
use diesel_models::process_tracker as storage;
use error_stack::ResultExt;
use router::{
configs::settings::{CmdLineConf, Settings},
core::errors::{self, CustomResult},
logger, routes, services,
core::{
errors::{self, CustomResult},
health_check::HealthCheckInterface,
},
logger, routes,
services::{self, api},
types::storage::ProcessTrackerExt,
workflows,
};
use router_env::{instrument, tracing};
use scheduler::{
consumer::workflows::ProcessTrackerWorkflow, errors::ProcessTrackerError,
workflows::ProcessTrackerWorkflows, SchedulerAppState,
};
use serde::{Deserialize, Serialize};
use storage_impl::errors::ApplicationError;
use strum::EnumString;
use tokio::sync::{mpsc, oneshot};

Expand Down Expand Up @@ -68,6 +76,19 @@ async fn main() -> CustomResult<(), ProcessTrackerError> {
[router_env::service_name!()],
);

#[allow(clippy::expect_used)]
let web_server = Box::pin(start_web_server(
state.clone(),
scheduler_flow_str.to_string(),
))
.await
.expect("Failed to create the server");

tokio::spawn(async move {
let _ = web_server.await;
logger::error!("The health check probe stopped working!");
});

logger::debug!(startup_config=?state.conf);

start_scheduler(&state, scheduler_flow, (tx, rx)).await?;
Expand All @@ -76,6 +97,106 @@ async fn main() -> CustomResult<(), ProcessTrackerError> {
Ok(())
}

pub async fn start_web_server(
state: routes::AppState,
service: String,
) -> errors::ApplicationResult<Server> {
let server = state
.conf
.scheduler
.as_ref()
.ok_or(ApplicationError::InvalidConfigurationValueError(
"Scheduler server is invalidly configured".into(),
))?
.server
.clone();

let web_server = actix_web::HttpServer::new(move || {
actix_web::App::new().service(Health::server(state.clone(), service.clone()))
})
.bind((server.host.as_str(), server.port))?
.workers(server.workers)
.run();
let _ = web_server.handle();

Ok(web_server)
}

pub struct Health;

impl Health {
pub fn server(state: routes::AppState, service: String) -> Scope {
web::scope("health")
.app_data(web::Data::new(state))
.app_data(web::Data::new(service))
.service(web::resource("").route(web::get().to(health)))
.service(web::resource("/ready").route(web::get().to(deep_health_check)))
}
}

#[instrument(skip_all)]
pub async fn health() -> impl actix_web::Responder {
logger::info!("Scheduler health was called");
actix_web::HttpResponse::Ok().body("Scheduler health is good")
}
#[instrument(skip_all)]
pub async fn deep_health_check(
state: web::Data<routes::AppState>,
service: web::Data<String>,
) -> impl actix_web::Responder {
let report = deep_health_check_func(state, service).await;
match report {
Ok(response) => services::http_response_json(
serde_json::to_string(&response)
.map_err(|err| {
logger::error!(serialization_error=?err);
})
.unwrap_or_default(),
),
Err(err) => api::log_and_return_error_response(err),
}
}
#[instrument(skip_all)]
pub async fn deep_health_check_func(
state: web::Data<routes::AppState>,
service: web::Data<String>,
) -> errors::RouterResult<SchedulerHealthCheckResponse> {
logger::info!("{} deep health check was called", service.into_inner());

logger::debug!("Database health check begin");

let db_status = state.health_check_db().await.map(|_| true).map_err(|err| {
error_stack::report!(errors::ApiErrorResponse::HealthCheckError {
component: "Database",
message: err.to_string()
})
})?;

logger::debug!("Database health check end");

logger::debug!("Redis health check begin");

let redis_status = state
.health_check_redis()
.await
.map(|_| true)
.map_err(|err| {
error_stack::report!(errors::ApiErrorResponse::HealthCheckError {
component: "Redis",
message: err.to_string()
})
})?;

logger::debug!("Redis health check end");

let response = SchedulerHealthCheckResponse {
database: db_status,
redis: redis_status,
};

Ok(response)
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, EnumString)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
Expand Down
19 changes: 16 additions & 3 deletions crates/router/src/connector/cybersource/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,22 @@ impl TryFrom<&types::SetupMandateRouterData> for CybersourceZeroMandateRequest {
utils::get_unimplemented_payment_method_error_message("Cybersource"),
))?,
},
_ => Err(errors::ConnectorError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("Cybersource"),
))?,
payments::PaymentMethodData::CardRedirect(_)
| payments::PaymentMethodData::PayLater(_)
| payments::PaymentMethodData::BankRedirect(_)
| payments::PaymentMethodData::BankDebit(_)
| payments::PaymentMethodData::BankTransfer(_)
| payments::PaymentMethodData::Crypto(_)
| payments::PaymentMethodData::MandatePayment
| payments::PaymentMethodData::Reward
| payments::PaymentMethodData::Upi(_)
| payments::PaymentMethodData::Voucher(_)
| payments::PaymentMethodData::GiftCard(_)
| payments::PaymentMethodData::CardToken(_) => {
Err(errors::ConnectorError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("Cybersource"),
))?
}
};

let processing_information = ProcessingInformation {
Expand Down
3 changes: 3 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,6 @@ pub const MAX_SESSION_EXPIRY: u32 = 7890000;
pub const MIN_SESSION_EXPIRY: u32 = 60;

pub const LOCKER_HEALTH_CALL_PATH: &str = "/health";

// URL for checking the outgoing call
pub const OUTGOING_CALL_URL: &str = "https://api.stripe.com/healthcheck";
6 changes: 6 additions & 0 deletions crates/router/src/core/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ pub enum ConnectorError {
InvalidConnectorConfig { config: &'static str },
}

#[derive(Debug, thiserror::Error)]
pub enum HealthCheckOutGoing {
#[error("Outgoing call failed with error: {message}")]
OutGoingFailed { message: String },
}

#[derive(Debug, thiserror::Error)]
pub enum VaultError {
#[error("Failed to save card in card vault")]
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/core/errors/api_error_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ pub enum ApiErrorResponse {
WebhookInvalidMerchantSecret,
#[error(error_type = ErrorType::InvalidRequestError, code = "IR_19", message = "{message}")]
CurrencyNotSupported { message: String },
#[error(error_type = ErrorType::ServerNotAvailable, code= "HE_00", message = "{component} health check is failiing with error: {message}")]
#[error(error_type = ErrorType::ServerNotAvailable, code= "HE_00", message = "{component} health check is failing with error: {message}")]
HealthCheckError {
component: &'static str,
message: String,
Expand Down
Loading

0 comments on commit dc31674

Please sign in to comment.