-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(payouts): implement KVRouterStore #3889
Conversation
f9d186b
to
d5494ad
Compare
refactor(payouts): update payouts feature flag dependency and consumption throughout crates
d4755d3
to
8e81bed
Compare
d6295ea
to
8e81bed
Compare
pub async fn validate_uniqueness_of_payout_id_against_merchant_id( | ||
db: &dyn StorageInterface, | ||
payout_id: &str, | ||
merchant_id: &str, | ||
storage_scheme: storage::enums::MerchantStorageScheme, | ||
) -> RouterResult<Option<storage::Payouts>> { | ||
let payout = db | ||
.find_payout_by_merchant_id_payout_id(merchant_id, payout_id) | ||
.find_payout_by_merchant_id_payout_id(merchant_id, payout_id, storage_scheme) | ||
.await; | ||
match payout { | ||
Err(err) => { | ||
if err.current_context().is_db_not_found() { | ||
// Empty vec should be returned by query in case of no results, this check exists just | ||
// to be on the safer side. Fixed this, now vector is not returned but should check the flow in detail later. | ||
Ok(None) | ||
} else { | ||
Err(err | ||
let erc = err.current_context(); | ||
match erc { | ||
StorageError::ValueNotFound(_) => Ok(None), | ||
_ => Err(err | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed while finding payout_attempt, database error")) | ||
.attach_printable("Failed while finding payout_attempt, database error")), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the correct way of implementing this function, can be confusing for some instance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-looking at this function, it looks good to me.
It checks whether or not the resource exists in DB, and returns an optional result
If Err is returned, it was due to external DB issues.
If Ok(None) is returned, DB call was successful but payout was not found
If Ok(Some) is returned, DB call was successful and payout with given ID already exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please have a look at fn generic_find_by_id_optional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can have an function named something like get_optional_payout_by_merchant_id_payout_id
in PayoutInterface which would be calling generic_find_by_id_optional
crates/router/src/db.rs
Outdated
+ refund::RefundInterface | ||
+ reverse_lookup::ReverseLookupInterface | ||
+ cards_info::CardsInfoInterface | ||
+ merchant_key_store::MerchantKeyStoreInterface | ||
+ MasterKeyInterface | ||
+ payment_link::PaymentLinkInterface | ||
+ RedisConnInterface | ||
+ RequestIdStore | ||
+ business_profile::BusinessProfileInterface | ||
+ OrganizationInterface | ||
+ routing_algorithm::RoutingAlgorithmInterface | ||
+ gsm::GsmInterface | ||
+ user::UserInterface | ||
+ user_role::UserRoleInterface | ||
+ authorization::AuthorizationInterface | ||
+ user::sample_data::BatchSampleDataInterface | ||
+ health_check::HealthCheckDbInterface | ||
+ role::RoleInterface | ||
+ 'static | ||
{ | ||
fn get_scheduler_db(&self) -> Box<dyn scheduler::SchedulerInterface>; | ||
} | ||
|
||
#[cfg(feature = "payouts")] | ||
#[async_trait::async_trait] | ||
pub trait StorageInterface: | ||
Send | ||
+ Sync | ||
+ dyn_clone::DynClone | ||
+ address::AddressInterface | ||
+ api_keys::ApiKeyInterface | ||
+ blocklist_lookup::BlocklistLookupInterface | ||
+ configs::ConfigInterface | ||
+ capture::CaptureInterface | ||
+ customers::CustomerInterface | ||
+ dashboard_metadata::DashboardMetadataInterface | ||
+ dispute::DisputeInterface | ||
+ ephemeral_key::EphemeralKeyInterface | ||
+ events::EventInterface | ||
+ file::FileMetadataInterface | ||
+ FraudCheckInterface | ||
+ locker_mock_up::LockerMockUpInterface | ||
+ mandate::MandateInterface | ||
+ merchant_account::MerchantAccountInterface | ||
+ merchant_connector_account::ConnectorAccessToken | ||
+ merchant_connector_account::MerchantConnectorAccountInterface | ||
+ PaymentAttemptInterface | ||
+ PaymentIntentInterface | ||
+ payment_method::PaymentMethodInterface | ||
+ blocklist::BlocklistInterface | ||
+ blocklist_fingerprint::BlocklistFingerprintInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jarnura and @SanchithHegde can we verify this change, its being duplicated for only payouts interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added an empty PayoutsInterface
and PayoutAttemptInterface
for instances where payouts feature is not enabled. Similar to how it's done for pub trait Connector:
self.diesel_store | ||
.update_payout_by_merchant_id_payout_id(merchant_id, payout_id, payout) | ||
.update_payout(this, payout_update, storage_scheme) | ||
.await | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can u pass instrument on every db function
} | ||
|
||
#[cfg(feature = "payouts")] | ||
impl UniqueConstraints for diesel_models::Payouts { | ||
fn unique_constraints(&self) -> Vec<String> { | ||
vec![format!("po_{}_{}", self.merchant_id, self.payout_id)] | ||
} | ||
fn table_name(&self) -> &str { | ||
"Payouts" | ||
} | ||
} | ||
|
||
#[cfg(feature = "payouts")] | ||
impl UniqueConstraints for diesel_models::PayoutAttempt { | ||
fn unique_constraints(&self) -> Vec<String> { | ||
vec![format!( | ||
"poa_{}_{}", | ||
self.merchant_id, self.payout_attempt_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dracarys18 can check this
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add intruments in such funcs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ci checks are failing along with merge conflicts can you fix all
ce878c1
to
af6a261
Compare
@@ -76,6 +77,19 @@ impl PaymentTokenData { | |||
pub fn wallet_token(payment_method_id: String) -> Self { | |||
Self::WalletToken(WalletTokenData { payment_method_id }) | |||
} | |||
|
|||
pub fn get_token(&self) -> &String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Chethan-rao - can you review this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case of cards, get_token
function doesn't really does what is says. Because cards have an object data as opposed to bank_transfer which has only one token field. I feel its better to remove this and generate token for bank transfer by explicitly matching on it
None, | ||
PaymentTokenData::temporary_generic(generate_id(consts::ID_LENGTH, "token")), | ||
), | ||
}; | ||
|
||
#[cfg(feature = "payouts")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Chethan-rao It's consumed here
e4b6d58
to
73d0d29
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dashboard specific changes looks good.
Type of Change
Description
This PR includes below changes
payouts
feature throughout cratesExplained in issue - #3652
Additional Changes
Motivation and Context
How did you test it?
By verifying existing payout functionalities are working as expected using KV
Checklist
cargo +nightly fmt --all
cargo clippy