Skip to content

Commit b38f461

Browse files
authored
chore: Preparation for publishing SDK (#31)
1 parent 76b0a2a commit b38f461

13 files changed

+162
-37
lines changed

.github/workflows/ci.yaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ env:
88
CARGO_TERM_COLOR: always
99

1010
jobs:
11+
rustfmt:
12+
name: Style & Lint
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v2
16+
- name: rustfmt
17+
run: cargo fmt -- --check
18+
- name: Rigorous lint via Clippy
19+
run: cargo clippy --all-targets --all-features -- -D warnings
1120
build_rust:
1221
runs-on: ubuntu-latest
1322
env:
@@ -19,8 +28,6 @@ jobs:
1928
run: cargo build --verbose
2029
- name: Cargo Check
2130
run: cargo check
22-
- name: Rustfmt
23-
run: cargo fmt -- --check
2431
- name: Unit Tests
2532
run: cargo test --lib
2633
- name: Doc Tests

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
[package]
22
name = "momento"
33
version = "0.1.0"
4-
authors = ["Matt Straathof <[email protected]>"]
4+
authors = ["momento"]
55
edition = "2018"
6+
description = "Client SDK for Momento services"
7+
readme = "README.md"
8+
license = "Apache-2.0"
9+
license-file = "LICENSE"
10+
repository = "https://github.com/momentohq/client-sdk-rust"
611

712
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
813

README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Momento client-sdk-rust
2+
3+
:warning: Experimental SDK :warning:
4+
5+
Rust SDK for Momento is experimental and under active development.
6+
There could be non-backward compatible changes or removal in the future.
7+
Please be aware that you may need to update your source code with the current version of the SDK when its version gets upgraded.
8+
9+
---
10+
11+
<br/>
12+
13+
Rust SDK for Momento, a serverless cache that automatically scales without any of the operational overhead required by traditional caching solutions.
14+
15+
<br/>
16+
17+
## Getting Started :running:
18+
19+
### Requirements
20+
21+
- A Momento Auth Token is required, you can generate one using the [Momento CLI](https://github.com/momentohq/momento-cli)
22+
23+
<br/>
24+
25+
### Using Momento
26+
27+
```rust
28+
use std::env;
29+
use momento::simple_cache_client::SimpleCacheClient;
30+
31+
// Initializing Momento
32+
let auth_token = env::var("TEST_AUTH_TOKEN").expect("env var TEST_AUTH_TOKEN must be set");
33+
let item_default_ttl_seconds = 60
34+
let mut cache_client = SimpleCacheClient::new(auth_token, item_default_ttl_seconds).await.unwrap();
35+
36+
// Creating a cache named "cache"
37+
let cache_name = String::from("cache");
38+
cache_client.create_cache(&cache_name).await.unwrap()
39+
40+
// Sets key with default TTL and get value with that key
41+
let key = String::from("my_key");
42+
let value = String::from("my_value");
43+
cache_client.set(&cache_name, key.clone(), value.clone(), None).await.unwrap();
44+
let result = cache_client.get(&cache_name, key.clone()).await.unwrap();
45+
println!("Looked up value: {}", result.value);
46+
47+
// Sets key with TTL of 5 seconds
48+
cache_client.set(&cache_name, key.clone(), value.clone(), 5).await.unwrap();
49+
50+
// Permanently deletes cache
51+
cache_client.delete_cache(&cache_name).await.unwrap();
52+
```
53+
54+
<br/>
55+
56+
## Running Tests :zap:
57+
58+
Doc and integration tests require an auth token for testing. Set the env var `TEST_AUTH_TOKEN` to
59+
provide it.
60+
61+
Running unit tests:
62+
63+
```
64+
cargo test --lib
65+
```
66+
67+
Running doc tests:
68+
69+
```
70+
TEST_AUTH_TOKEN=<auth token> cargo test --doc
71+
```
72+
73+
Running integration tests:
74+
75+
```
76+
TEST_AUTH_TOKEN=<auth token> cargo test --tests
77+
```

src/endpoint_resolver.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ impl MomentoEndpointsResolver {
1616
let claims = utils::get_claims(auth_token);
1717
let control_endpoint = MomentoEndpointsResolver::get_control_endpoint(&claims, hosted_zone);
1818
let data_endpoint = MomentoEndpointsResolver::get_data_endpoint(&claims, hosted_zone);
19-
return MomentoEndpoints {
19+
MomentoEndpoints {
2020
control_endpoint,
2121
data_endpoint,
22-
};
22+
}
2323
}
2424

2525
fn get_control_endpoint(claims: &Claims, hosted_zone: &Option<String>) -> String {
26-
return MomentoEndpointsResolver::get_control_endpoint_from_hosted_zone(hosted_zone)
27-
.unwrap_or_else(|| format!("https://{}:443", claims.cp));
26+
MomentoEndpointsResolver::get_control_endpoint_from_hosted_zone(hosted_zone)
27+
.unwrap_or_else(|| format!("https://{}:443", claims.cp))
2828
}
2929

3030
fn get_data_endpoint(claims: &Claims, hosted_zone: &Option<String>) -> String {
31-
return MomentoEndpointsResolver::get_data_endpoint_from_hosted_zone(hosted_zone)
32-
.unwrap_or_else(|| format!("https://{}:443", claims.c));
31+
MomentoEndpointsResolver::get_data_endpoint_from_hosted_zone(hosted_zone)
32+
.unwrap_or_else(|| format!("https://{}:443", claims.c))
3333
}
3434

3535
fn get_control_endpoint_from_hosted_zone(hosted_zone: &Option<String>) -> Option<String> {

src/grpc/cache_header_interceptor.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ pub struct CacheHeaderInterceptor {
66
impl tonic::service::Interceptor for CacheHeaderInterceptor {
77
fn call(&mut self, request: tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status> {
88
let request_metadata = request.metadata().clone();
9-
let mut result = tonic::Request::new(request.into_inner());
9+
let mut result = {
10+
let message = request.into_inner();
11+
tonic::Request::new(message)
12+
};
1013
result.metadata_mut().insert(
1114
"authorization",
1215
tonic::metadata::AsciiMetadataValue::from_str(self.auth_key.as_str()).unwrap(),

src/response/cache_get_response.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1+
/// Encapsulates the status of a cache get operation.
12
#[derive(Debug)]
23
pub enum MomentoGetStatus {
4+
/// Status if an item was found in cache.
35
HIT,
6+
/// Status if an item was not found in cache.
47
MISS,
58
ERROR,
69
}
710

11+
/// Response for a cache get operation.
812
#[derive(Debug)]
913
pub struct MomentoGetResponse {
14+
/// The result of a cache get operation.
1015
pub result: MomentoGetStatus,
16+
/// Value stored in the cache as u8 vector.
1117
pub value: Vec<u8>,
1218
}
1319

1420
impl MomentoGetResponse {
21+
/// Returns a value stored in the cache as a UTF-8.
1522
pub fn as_string(&self) -> &str {
1623
return std::str::from_utf8(self.value.as_slice()).unwrap_or_default();
1724
}

src/response/cache_set_response.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
/// Encapsulates the status of a cache set operation
12
#[derive(Debug)]
23
pub enum MomentoSetStatus {
34
OK,
45
ERROR,
56
}
7+
8+
/// Response for a cache set operation.
69
#[derive(Debug)]
710
pub struct MomentoSetResponse {
11+
/// The result of a cache set operation.
812
pub result: MomentoSetStatus,
913
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
use serde::{Deserialize, Serialize};
22

3+
/// The results of a singing key operation.
34
#[derive(Debug, Serialize, Deserialize)]
45
pub struct MomentoCreateSigningKeyResponse {
6+
/// The ID of the key
57
pub key_id: String,
8+
/// Key itself
69
pub key: String,
10+
/// When the key expires
711
pub expires_at: u64,
12+
/// Endpoint for creating a pre-signed url
813
pub endpoint: String,
914
}

src/response/error.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
11
use tonic::codegen::http;
22

3+
/// Exception type for resulting from invalid interactions with Momento Services.
34
#[derive(Debug)]
45
pub enum MomentoError {
6+
/// Momento Service encountered an unexpected exception while trying to fulfill the request.
57
InternalServerError(String),
8+
/// Invalid parameters sent to Momento Services.
69
BadRequest(String),
10+
/// Insufficient permissions to execute an operation.
711
PermissionDenied(String),
12+
/// Authentication token is not provided or is invalid.
813
Unauthenticated(String),
14+
/// Requested resource or the resource on which an operation was requested doesn't exist.
915
NotFound(String),
16+
/// A resource already exists.
1017
AlreadyExists(String),
18+
/// Operation was cancelled.
1119
Cancelled(String),
20+
/// Requested operation did not complete in allotted time.
1221
Timeout(String),
22+
/// Requested operation couldn't be completed because system limits were hit.
1323
LimitExceeded(String),
24+
/// Represents all client side exceptions thrown by the SDK.
25+
/// his exception typically implies that the request wasn't sent to the service successfully or if the service responded, the sdk couldn't interpret the response.
26+
/// An example would be SDK client was unable to convert the user provided data into a valid request that was expected by the service.
1427
ClientSdkError(String),
28+
/// SDK client side validation fails.
1529
InvalidArgument(String),
1630
}
1731

@@ -86,7 +100,7 @@ fn status_to_error(status: tonic::Status) -> MomentoError {
86100
| tonic::Code::Aborted
87101
| tonic::Code::Internal
88102
| tonic::Code::Unavailable
89-
| tonic::Code::DataLoss
90-
| _ => MomentoError::InternalServerError(status.message().to_string()),
103+
| tonic::Code::DataLoss => MomentoError::InternalServerError(status.message().to_string()),
104+
_ => MomentoError::InternalServerError(status.message().to_string()),
91105
}
92106
}

src/response/list_cache_response.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
/// Response cache object for list of caches.
12
#[derive(Debug)]
23
pub struct MomentoCache {
4+
/// Name of the cache associated with a specific client.
35
pub cache_name: String,
46
}
57

8+
/// The result of a cache list operation.
69
#[derive(Debug)]
710
pub struct MomentoListCacheResult {
11+
/// Vector of cache information defined in MomentoCache.
812
pub caches: Vec<MomentoCache>,
13+
/// Next Page Token returned by Simple Cache Service along with the list of caches.
914
pub next_token: String,
1015
}

src/simple_cache_client.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl SimpleCacheClient {
165165
data_client: data_client.unwrap(),
166166
item_default_ttl_seconds: default_ttl_seconds,
167167
};
168-
return Ok(simple_cache_client);
168+
Ok(simple_cache_client)
169169
}
170170

171171
async fn build_control_client(
@@ -186,7 +186,7 @@ impl SimpleCacheClient {
186186
},
187187
);
188188
let client = ScsControlClient::new(interceptor);
189-
return Ok(client);
189+
Ok(client)
190190
}
191191

192192
async fn build_data_client(
@@ -206,7 +206,7 @@ impl SimpleCacheClient {
206206
},
207207
);
208208
let client = ScsClient::new(interceptor);
209-
return Ok(client);
209+
Ok(client)
210210
}
211211

212212
/// Creates a new Momento cache
@@ -215,7 +215,7 @@ impl SimpleCacheClient {
215215
///
216216
/// * `name` - name of cache to create
217217
pub async fn create_cache(&mut self, name: &str) -> Result<(), MomentoError> {
218-
utils::is_cache_name_valid(&name)?;
218+
utils::is_cache_name_valid(name)?;
219219
let request = Request::new(CreateCacheRequest {
220220
cache_name: name.to_string(),
221221
});
@@ -245,7 +245,7 @@ impl SimpleCacheClient {
245245
/// # })
246246
/// ```
247247
pub async fn delete_cache(&mut self, name: &str) -> Result<(), MomentoError> {
248-
utils::is_cache_name_valid(&name)?;
248+
utils::is_cache_name_valid(name)?;
249249
let request = Request::new(DeleteCacheRequest {
250250
cache_name: name.to_string(),
251251
});
@@ -287,7 +287,7 @@ impl SimpleCacheClient {
287287
.collect();
288288
let response = MomentoListCacheResult {
289289
caches,
290-
next_token: res.next_token.to_string(),
290+
next_token: res.next_token,
291291
};
292292
Ok(response)
293293
}
@@ -301,9 +301,7 @@ impl SimpleCacheClient {
301301
&mut self,
302302
ttl_minutes: u32,
303303
) -> Result<MomentoCreateSigningKeyResponse, MomentoError> {
304-
let request = Request::new(CreateSigningKeyRequest {
305-
ttl_minutes: ttl_minutes,
306-
});
304+
let request = Request::new(CreateSigningKeyRequest { ttl_minutes });
307305
let res = self
308306
.control_client
309307
.create_signing_key(request)
@@ -327,7 +325,7 @@ impl SimpleCacheClient {
327325
///
328326
/// * `key_id` - the ID of the key to revoke
329327
pub async fn revoke_signing_key(&mut self, key_id: &str) -> Result<(), MomentoError> {
330-
utils::is_key_id_valid(&key_id)?;
328+
utils::is_key_id_valid(key_id)?;
331329
let request = Request::new(RevokeSigningKeyRequest {
332330
key_id: key_id.to_string(),
333331
});
@@ -369,10 +367,10 @@ impl SimpleCacheClient {
369367
body: I,
370368
ttl_seconds: Option<u64>,
371369
) -> Result<MomentoSetResponse, MomentoError> {
372-
utils::is_cache_name_valid(&cache_name)?;
370+
utils::is_cache_name_valid(cache_name)?;
373371
let temp_ttl = ttl_seconds.unwrap_or(self.item_default_ttl_seconds);
374372
let ttl_to_use = match utils::is_ttl_valid(&temp_ttl) {
375-
Ok(_) => temp_ttl * 1000 as u64,
373+
Ok(_) => temp_ttl * 1000_u64,
376374
Err(e) => return Err(e),
377375
};
378376
let mut request = tonic::Request::new(SetRequest {
@@ -382,7 +380,7 @@ impl SimpleCacheClient {
382380
});
383381
request.metadata_mut().append(
384382
"cache",
385-
tonic::metadata::AsciiMetadataValue::from_str(&cache_name).unwrap(),
383+
tonic::metadata::AsciiMetadataValue::from_str(cache_name).unwrap(),
386384
);
387385
let _ = self.data_client.set(request).await?;
388386
Ok(MomentoSetResponse {
@@ -424,16 +422,16 @@ impl SimpleCacheClient {
424422
cache_name: &str,
425423
key: I,
426424
) -> Result<MomentoGetResponse, MomentoError> {
427-
utils::is_cache_name_valid(&cache_name)?;
425+
utils::is_cache_name_valid(cache_name)?;
428426
let mut request = tonic::Request::new(GetRequest {
429427
cache_key: key.into_bytes(),
430428
});
431429
request.metadata_mut().append(
432430
"cache",
433-
tonic::metadata::AsciiMetadataValue::from_str(&cache_name).unwrap(),
431+
tonic::metadata::AsciiMetadataValue::from_str(cache_name).unwrap(),
434432
);
435433
let response = self.data_client.get(request).await?.into_inner();
436-
return match response.result() {
434+
match response.result() {
437435
ECacheResult::Hit => Ok(MomentoGetResponse {
438436
result: MomentoGetStatus::HIT,
439437
value: response.cache_body,
@@ -443,6 +441,6 @@ impl SimpleCacheClient {
443441
value: response.cache_body,
444442
}),
445443
_ => todo!(),
446-
};
444+
}
447445
}
448446
}

0 commit comments

Comments
 (0)