Skip to content
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

Remove idempotency token trait #571

Merged
merged 2 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ class IdempotencyTokenProviderCustomization : NamedSectionGenerator<ServiceConfi
override fun section(section: ServiceConfig): Writable {
return when (section) {
is ServiceConfig.ConfigStruct -> writable {
rust("pub (crate) make_token: Box<dyn #T::MakeIdempotencyToken>,", RuntimeType.IdempotencyToken)
rust("pub (crate) make_token: #T::IdempotencyTokenProvider,", RuntimeType.IdempotencyToken)
}
ServiceConfig.ConfigImpl -> emptySection
ServiceConfig.BuilderStruct -> writable {
rust("make_token: Option<Box<dyn #T::MakeIdempotencyToken>>,", RuntimeType.IdempotencyToken)
rust("make_token: Option<#T::IdempotencyTokenProvider>,", RuntimeType.IdempotencyToken)
}
ServiceConfig.BuilderImpl -> writable {
rust(
"""
pub fn make_token(mut self, make_token: impl #T::MakeIdempotencyToken + 'static) -> Self {
self.make_token = Some(Box::new(make_token));
pub fn make_token(mut self, make_token: impl Into<#T::IdempotencyTokenProvider>) -> Self {
self.make_token = Some(make_token.into());
self
}
""",
RuntimeType.IdempotencyToken
)
}
ServiceConfig.BuilderBuild -> writable {
rust("make_token: self.make_token.unwrap_or_else(|| Box::new(#T::default_provider())),", RuntimeType.IdempotencyToken)
rust("make_token: self.make_token.unwrap_or_else(#T::default_provider),", RuntimeType.IdempotencyToken)
}
}
}
Expand Down
57 changes: 46 additions & 11 deletions rust-runtime/inlineable/src/idempotency_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,58 @@ pub(crate) fn uuid_v4(input: u128) -> String {
out
}

pub trait MakeIdempotencyToken: Send + Sync {
fn make_idempotency_token(&self) -> String;
/// IdempotencyTokenProvider generates idempotency tokens for idempotency API requests
///
/// Generally, customers will not need to interact with this at all. A sensible default will be
/// provided automatically during config construction. However, if you need deterministic behavior
/// for testing, two options are available:
/// 1. Utilize the From<&'static str>` implementation to hard code an idempotency token
/// 2. Seed the token provider with [`IdempotencyTokenProvider::with_seed`](IdempotencyTokenProvider::with_seed)
pub struct IdempotencyTokenProvider {
inner: Inner,
}

pub fn default_provider() -> impl MakeIdempotencyToken {
Mutex::new(fastrand::Rng::new())
enum Inner {
Static(&'static str),
Random(Mutex<fastrand::Rng>),
}

impl MakeIdempotencyToken for Mutex<fastrand::Rng> {
fn make_idempotency_token(&self) -> String {
let input: u128 = self.lock().unwrap().u128(..);
uuid_v4(input)
pub fn default_provider() -> IdempotencyTokenProvider {
IdempotencyTokenProvider::random()
}

impl From<&'static str> for IdempotencyTokenProvider {
fn from(token: &'static str) -> Self {
Self::fixed(token)
}
}

impl MakeIdempotencyToken for &'static str {
fn make_idempotency_token(&self) -> String {
self.to_string()
impl IdempotencyTokenProvider {
pub fn make_idempotency_token(&self) -> String {
match &self.inner {
Inner::Static(token) => token.to_string(),
Inner::Random(rng) => {
let input: u128 = rng.lock().unwrap().u128(..);
uuid_v4(input)
}
}
}

pub fn with_seed(seed: u64) -> Self {
Self {
inner: Inner::Random(Mutex::new(fastrand::Rng::with_seed(seed))),
}
}

pub fn random() -> Self {
Self {
inner: Inner::Random(Mutex::new(fastrand::Rng::new())),
}
}

pub fn fixed(token: &'static str) -> Self {
Self {
inner: Inner::Static(token),
}
}
}
7 changes: 2 additions & 5 deletions rust-runtime/inlineable/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ mod rest_xml_wrapped_errors;
#[cfg(test)]
mod test {
use crate::idempotency_token;
use crate::idempotency_token::uuid_v4;
use crate::idempotency_token::{uuid_v4, IdempotencyTokenProvider};
use proptest::prelude::*;
use std::sync::Mutex;

#[test]
fn test_uuid() {
Expand All @@ -36,7 +35,6 @@ mod test {
#[test]
fn default_token_generator_smoke_test() {
// smoke test to make sure the default token generator produces a token-like object
use crate::idempotency_token::MakeIdempotencyToken;
assert_eq!(
idempotency_token::default_provider()
.make_idempotency_token()
Expand All @@ -47,8 +45,7 @@ mod test {

#[test]
fn token_generator() {
let provider = Mutex::new(fastrand::Rng::with_seed(123));
use crate::idempotency_token::MakeIdempotencyToken;
let provider = IdempotencyTokenProvider::with_seed(123);
assert_eq!(
provider.make_idempotency_token(),
"b4021a03-ae07-4db5-fc1b-38bf919691f8"
Expand Down