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

Implement an identity cache in aws-smithy-runtime #3062

Merged
merged 12 commits into from
Oct 17, 2023

Conversation

jdisanti
Copy link
Collaborator

This PR adds a ResolveCachedIdentity trait, and adapts the existing LazyCredentialsCache implementation to it. It does NOT make this cache used yet, as that will be done as a separate PR to keep code review smaller.

Notable differences from the credentials cache:

  • Supports multiple different identity types and identity resolvers
  • Applies cache partitioning to the SharedIdentityResolver so that operation config overrides of the identity resolver will result in the correct identity being resolved.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@jdisanti jdisanti requested a review from a team as a code owner October 12, 2023 00:27
@jdisanti jdisanti force-pushed the jdisanti-identity-cache branch 3 times, most recently from 80861fb to 67665e7 Compare October 12, 2023 23:36
@smithy-lang smithy-lang deleted a comment from github-actions bot Oct 12, 2023
@smithy-lang smithy-lang deleted a comment from github-actions bot Oct 12, 2023
@jdisanti jdisanti force-pushed the jdisanti-identity-cache branch from 67665e7 to 4574ba7 Compare October 12, 2023 23:55
@smithy-lang smithy-lang deleted a comment from github-actions bot Oct 12, 2023
@github-actions
Copy link

A new generated diff is ready to view.

  • AWS SDK (ignoring whitespace)
  • No codegen difference in the Client Test
  • No codegen difference in the Server Test
  • No codegen difference in the Server Test Python
  • No codegen difference in the Server Test Typescript

A new doc preview is ready to view.

Copy link
Collaborator

@rcoh rcoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

look good — some potential other ideas in line

Comment on lines 113 to 122
pub fn buffer_time_jitter_fraction(mut self, buffer_time_jitter_fraction: fn() -> f64) -> Self {
self.set_buffer_time_jitter_fraction(Some(buffer_time_jitter_fraction));
self
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be pub, even feature gated?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like this is even used in tests anymore. I'm going to make it private and cfg(test) in case its needed in the future.

LazyCache::new(
self.time_source.unwrap_or_default(),
self.sleep_impl.unwrap_or_else(|| {
default_async_sleep().expect("no default sleep implementation available")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this come from a runtime plugin / runtime components?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call out. I refactored it so that these come in through a RuntimeComponents argument on ResolveIdentity so that they will work correctly with config overrides.

Comment on lines 197 to 214
let mut partition = self.partitions.read().unwrap().get(&key).cloned();
if partition.is_none() {
let mut partitions = self.partitions.write().unwrap();
// Another thread could have inserted the partition before we acquired the lock,
// so double check before inserting it.
partitions
.entry(key)
.or_insert_with(|| ExpiringCache::new(self.buffer_time));
drop(partitions);

partition = self.partitions.read().unwrap().get(&key).cloned();
}
partition.expect("inserted above if not present")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it's so easy to mess up RWLock caches, you may want to consider writing the code in a way where you explictly drop() the locks

.or_insert_with(|| ExpiringCache::new(self.buffer_time));
drop(partitions);

partition = self.partitions.read().unwrap().get(&key).cloned();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this pattern only works for append-only caches, it may be worth noting that entries are never removed.

Comment on lines 288 to 306
let jitter = self
.buffer_time
.mul_f64((self.buffer_time_jitter_fraction)());

// Logging for cache miss should be emitted here as opposed to after the call to
// `cache.get_or_load` above. In the case of multiple threads concurrently executing
// `cache.get_or_load`, logging inside `cache.get_or_load` ensures that it is emitted
// only once for the first thread that succeeds in populating a cache value.
tracing::info!(
"identity cache miss occurred; added new AWS identity (took {:?})",
time.now().duration_since(start_time)
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably note the impact of jitter on the buffer time in the docs above.

NoCache.into_shared()
}

/// Configure a lazy identity cache.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more line that identities are lazily loaded when requested would probably be helpful here

fn resolve_cached_identity<'a>(
&'a self,
resolver: SharedIdentityResolver,
config_bag: &'a ConfigBag,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to be giving it the entire config bag? should this have just auth params instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identity resolution isn't supposed to have access to the auth parameters per the spec.

* SPDX-License-Identifier: Apache-2.0
*/

use std::future::Future;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want this to be in runtime-api instead? I think we've hit other issues where this primitive wasn't accessible to the dependency tree.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like aws-config is the only other place that uses it, and that depends on aws-smithy-runtime. So I think it's fine where it is. We can always move/re-export it later if we need to.

Base automatically changed from jdisanti-async-trait-lifetimes to main October 13, 2023 17:19
@jdisanti jdisanti requested a review from a team as a code owner October 13, 2023 17:19
@jdisanti jdisanti force-pushed the jdisanti-identity-cache branch from 4574ba7 to b7b7b97 Compare October 13, 2023 20:39
@github-actions
Copy link

A new generated diff is ready to view.

  • AWS SDK (ignoring whitespace)
  • No codegen difference in the Client Test
  • No codegen difference in the Server Test
  • No codegen difference in the Server Test Python
  • No codegen difference in the Server Test Typescript

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

  • AWS SDK (ignoring whitespace)
  • No codegen difference in the Client Test
  • No codegen difference in the Server Test
  • No codegen difference in the Server Test Python
  • No codegen difference in the Server Test Typescript

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

  • AWS SDK (ignoring whitespace)
  • No codegen difference in the Client Test
  • No codegen difference in the Server Test
  • No codegen difference in the Server Test Python
  • No codegen difference in the Server Test Typescript

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

  • AWS SDK (ignoring whitespace)
  • No codegen difference in the Client Test
  • No codegen difference in the Server Test
  • No codegen difference in the Server Test Python
  • No codegen difference in the Server Test Typescript

A new doc preview is ready to view.

@jdisanti jdisanti added this pull request to the merge queue Oct 17, 2023
Merged via the queue into main with commit d48acae Oct 17, 2023
40 of 41 checks passed
@jdisanti jdisanti deleted the jdisanti-identity-cache branch October 17, 2023 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants