-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: momento leaderboard client (#438)
Adds client functionality for the Momento Leaderboard API.
- Loading branch information
Showing
28 changed files
with
1,766 additions
and
22 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
use std::time::Duration; | ||
|
||
use crate::config::transport_strategy::TransportStrategy; | ||
|
||
/// Configuration for a Momento leaderboard client. | ||
/// | ||
/// Static, versioned configurations are provided for different environments: | ||
/// ``` | ||
/// use momento::leaderboard::configurations; | ||
/// | ||
/// /// Use laptop for local development | ||
/// let developer_config = configurations::Laptop::latest(); | ||
/// | ||
/// /// Use in_region for a typical server environment | ||
/// let server_config = configurations::InRegion::latest(); | ||
/// ``` | ||
/// If you have specific requirements, configurations can also be constructed manually: | ||
/// ``` | ||
/// use std::time::Duration; | ||
/// use momento::leaderboard::Configuration; | ||
/// use momento::config::grpc_configuration::{GrpcConfiguration, GrpcConfigurationBuilder}; | ||
/// use momento::config::transport_strategy::TransportStrategy; | ||
/// | ||
/// let config = Configuration::builder() | ||
/// .transport_strategy( | ||
/// TransportStrategy::builder() | ||
/// .grpc_configuration( | ||
/// GrpcConfiguration::builder() | ||
/// .deadline(Duration::from_millis(1000)) | ||
/// ) | ||
/// ); | ||
#[derive(Clone, Debug)] | ||
pub struct Configuration { | ||
/// Low-level options for network interactions with Momento. | ||
pub(crate) transport_strategy: TransportStrategy, | ||
} | ||
|
||
impl Configuration { | ||
/// First level of constructing a LeaderboardClient configuration. Must provide a [TransportStrategy] to continue. | ||
pub fn builder() -> ConfigurationBuilder<NeedsTransportStrategy> { | ||
ConfigurationBuilder(NeedsTransportStrategy(())) | ||
} | ||
|
||
/// Returns the duration the client will wait before terminating an RPC with a DeadlineExceeded error. | ||
pub fn client_timeout(&self) -> Duration { | ||
self.transport_strategy.grpc_configuration.deadline | ||
} | ||
} | ||
|
||
/// The initial state of the ConfigurationBuilder. | ||
pub struct ConfigurationBuilder<State>(State); | ||
|
||
/// The state of the ConfigurationBuilder when it is waiting for a transport strategy. | ||
pub struct NeedsTransportStrategy(()); | ||
|
||
/// The state of the ConfigurationBuilder when it is ready to build a Configuration. | ||
pub struct ReadyToBuild { | ||
transport_strategy: TransportStrategy, | ||
} | ||
|
||
impl ConfigurationBuilder<NeedsTransportStrategy> { | ||
/// Sets the transport strategy for the Configuration and returns | ||
/// the ConfigurationBuilder in the ReadyToBuild state. | ||
pub fn transport_strategy( | ||
self, | ||
transport_strategy: impl Into<TransportStrategy>, | ||
) -> ConfigurationBuilder<ReadyToBuild> { | ||
ConfigurationBuilder(ReadyToBuild { | ||
transport_strategy: transport_strategy.into(), | ||
}) | ||
} | ||
} | ||
|
||
impl ConfigurationBuilder<ReadyToBuild> { | ||
/// Constructs the Configuration with the given transport strategy. | ||
pub fn build(self) -> Configuration { | ||
Configuration { | ||
transport_strategy: self.0.transport_strategy, | ||
} | ||
} | ||
} | ||
|
||
impl From<ConfigurationBuilder<ReadyToBuild>> for Configuration { | ||
fn from(builder: ConfigurationBuilder<ReadyToBuild>) -> Configuration { | ||
builder.build() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
use std::time::Duration; | ||
|
||
use crate::config::grpc_configuration::GrpcConfiguration; | ||
use crate::config::transport_strategy::TransportStrategy; | ||
use crate::leaderboard::Configuration; | ||
|
||
/// Provides defaults suitable for a medium-to-high-latency dev environment. Permissive timeouts | ||
/// and relaxed latency and throughput targets. | ||
pub struct Laptop {} | ||
|
||
impl Laptop { | ||
/// Returns the latest prebuilt configuration. | ||
/// This is the recommended configuration for most users. | ||
/// | ||
/// NOTE: this config may change in future releases to take advantage of improvements | ||
/// we identify for default configurations. | ||
#[allow(dead_code)] | ||
pub fn latest() -> impl Into<Configuration> { | ||
Laptop::v1() | ||
} | ||
|
||
/// Returns the v1 prebuilt configuration. | ||
/// | ||
/// Versioning the prebuilt configurations allows users to opt-in to changes in the default | ||
/// configurations. This is useful for users who want to ensure that their application's | ||
/// behavior does not change unexpectedly. | ||
pub fn v1() -> impl Into<Configuration> { | ||
Configuration::builder().transport_strategy( | ||
TransportStrategy::builder().grpc_configuration( | ||
GrpcConfiguration::builder() | ||
.deadline(Duration::from_millis(15000)) | ||
.enable_keep_alives_with_defaults(), | ||
), | ||
) | ||
} | ||
} | ||
|
||
/// Provides defaults suitable for an environment where your client is running in the same | ||
/// region as the Momento service. It has more aggressive timeouts than the laptop config. | ||
pub struct InRegion {} | ||
|
||
impl InRegion { | ||
/// Returns the latest prebuilt configuration. | ||
/// This is the recommended configuration for most users. | ||
/// | ||
/// NOTE: this config may change in future releases to take advantage of improvements | ||
/// we identify for default configurations. | ||
#[allow(dead_code)] | ||
pub fn latest() -> impl Into<Configuration> { | ||
InRegion::v1() | ||
} | ||
|
||
/// Returns the v1 prebuilt configuration. | ||
/// | ||
/// Versioning the prebuilt configurations allows users to opt-in to changes in the default | ||
/// configurations. This is useful for users who want to ensure that their application's | ||
/// behavior does not change unexpectedly. | ||
#[allow(dead_code)] | ||
pub fn v1() -> impl Into<Configuration> { | ||
Configuration::builder().transport_strategy( | ||
TransportStrategy::builder().grpc_configuration( | ||
GrpcConfiguration::builder() | ||
.deadline(Duration::from_millis(1100)) | ||
.enable_keep_alives_with_defaults(), | ||
), | ||
) | ||
} | ||
} | ||
|
||
/// This config prioritizes keeping p99.9 latencies as low as possible, potentially sacrificing | ||
/// some throughput to achieve this. Use this config if low latency is more important in | ||
/// your application than availability. | ||
pub struct LowLatency {} | ||
|
||
impl LowLatency { | ||
/// Returns the latest prebuilt configuration. | ||
/// This is the recommended configuration for most users. | ||
/// | ||
/// NOTE: this config may change in future releases to take advantage of improvements | ||
/// we identify for default configurations. | ||
#[allow(dead_code)] | ||
pub fn latest() -> impl Into<Configuration> { | ||
LowLatency::v1() | ||
} | ||
|
||
/// Returns the v1 prebuilt configuration. | ||
/// | ||
/// Versioning the prebuilt configurations allows users to opt-in to changes in the default | ||
/// configurations. This is useful for users who want to ensure that their application's | ||
/// behavior does not change unexpectedly. | ||
pub fn v1() -> impl Into<Configuration> { | ||
Configuration::builder().transport_strategy( | ||
TransportStrategy::builder().grpc_configuration( | ||
GrpcConfiguration::builder() | ||
.deadline(Duration::from_millis(500)) | ||
.enable_keep_alives_with_defaults(), | ||
), | ||
) | ||
} | ||
} | ||
|
||
/// This config optimizes for lambda environments. | ||
/// | ||
/// In addition to the in region settings of [InRegion], this | ||
/// disables keep-alives. | ||
/// | ||
/// NOTE: keep-alives are very important for long-lived server environments where there may be periods of time | ||
/// when the connection is idle. However, they are very problematic for lambda environments where the lambda | ||
/// runtime is continuously frozen and unfrozen, because the lambda may be frozen before the "ACK" is received | ||
/// from the server. This can cause the keep-alive to timeout even though the connection is completely healthy. | ||
/// Therefore, keep-alives should be disabled in lambda and similar environments. | ||
pub struct Lambda {} | ||
|
||
impl Lambda { | ||
/// Latest recommended config for a typical lambda environment. | ||
/// | ||
/// NOTE: this config may change in future releases to take advantage of improvements | ||
/// we identify for default configurations. | ||
#[allow(dead_code)] | ||
pub fn latest() -> impl Into<Configuration> { | ||
Lambda::v1() | ||
} | ||
|
||
/// Returns the v1 prebuilt configuration. | ||
/// | ||
/// Versioning the prebuilt configurations allows users to opt-in to changes in the default | ||
/// configurations. This is useful for users who want to ensure that their application's | ||
/// behavior does not change unexpectedly. | ||
pub fn v1() -> impl Into<Configuration> { | ||
Configuration::builder().transport_strategy( | ||
TransportStrategy::builder().grpc_configuration( | ||
GrpcConfiguration::builder() | ||
.deadline(Duration::from_millis(1100)) | ||
.num_channels(1), | ||
), | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/// Configuration for the Momento leaderboard client. | ||
pub mod configuration; | ||
/// Pre-built configurations for the Momento leaderboard client. | ||
pub mod configurations; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
use crate::grpc::header_interceptor::HeaderInterceptor; | ||
use crate::leaderboard::leaderboard_client_builder::{ | ||
LeaderboardClientBuilder, NeedsConfiguration, | ||
}; | ||
use crate::leaderboard::Configuration; | ||
use crate::leaderboard::Leaderboard; | ||
|
||
use momento_protos::leaderboard::leaderboard_client as leaderboard_proto; | ||
use tonic::codegen::InterceptedService; | ||
use tonic::transport::Channel; | ||
|
||
/// Client to work with Momento Leaderboards. | ||
#[derive(Clone, Debug)] | ||
pub struct LeaderboardClient { | ||
data_clients: | ||
Vec<leaderboard_proto::LeaderboardClient<InterceptedService<Channel, HeaderInterceptor>>>, | ||
configuration: Configuration, | ||
} | ||
|
||
impl LeaderboardClient { | ||
/// Returns a builder to construct a `LeaderboardClient`. | ||
pub fn builder() -> LeaderboardClientBuilder<NeedsConfiguration> { | ||
LeaderboardClientBuilder(NeedsConfiguration {}) | ||
} | ||
|
||
pub(crate) fn new( | ||
data_clients: Vec< | ||
leaderboard_proto::LeaderboardClient<InterceptedService<Channel, HeaderInterceptor>>, | ||
>, | ||
configuration: Configuration, | ||
) -> Self { | ||
Self { | ||
data_clients, | ||
configuration, | ||
} | ||
} | ||
|
||
/// Returns a `Leaderboard` client to work with a specific leaderboard. | ||
pub fn leaderboard( | ||
&self, | ||
cache_name: impl Into<String>, | ||
leaderboard_name: impl Into<String>, | ||
) -> Leaderboard { | ||
Leaderboard::new( | ||
self.data_clients.clone(), | ||
self.configuration.client_timeout(), | ||
cache_name, | ||
leaderboard_name, | ||
) | ||
} | ||
} |
Oops, something went wrong.