fakecloud_swf/shared.rs
1//! Primitives shared across the Amazon SWF handlers: ARN synthesis, run-id
2//! minting, timestamps, and the type/token key derivation. Kept in one place so
3//! the register / describe / poll paths cannot diverge on wire format.
4
5/// Current time as awsJson1_0 epoch-seconds (a floating-point number). SWF's
6/// `Timestamp` shape carries no `@timestampFormat`, so awsJson1_0's default
7/// epoch-seconds applies (SWF returns e.g. `1420070400.123`).
8pub fn now_epoch() -> f64 {
9 chrono::Utc::now().timestamp_millis() as f64 / 1000.0
10}
11
12/// A fresh, AWS-shaped SWF run id: a base64url-ish opaque token AWS returns from
13/// `StartWorkflowExecution`. We mint a stable random 43-ish char id; the exact
14/// alphabet is opaque to clients, they only echo it back.
15pub fn new_run_id() -> String {
16 // Two v4 UUIDs (simple, no dashes) give a 64-hex opaque token, matching the
17 // opaque-string contract SWF run ids satisfy.
18 format!(
19 "{}{}",
20 uuid::Uuid::new_v4().simple(),
21 uuid::Uuid::new_v4().simple()
22 )
23}
24
25/// A fresh opaque task token (decision or activity). Clients treat it as opaque.
26pub fn new_task_token() -> String {
27 format!(
28 "AAAAK{}{}",
29 uuid::Uuid::new_v4().simple(),
30 uuid::Uuid::new_v4().simple()
31 )
32}
33
34/// Amazon SWF domain ARN, `arn:aws:swf:{region}:{account}:/domain/{name}`.
35pub fn domain_arn(region: &str, account: &str, name: &str) -> String {
36 format!("arn:aws:swf:{region}:{account}:/domain/{name}")
37}
38
39/// Internal storage key for an activity or workflow type: `name` + a unit
40/// separator + `version`. The separator can never appear in a Smithy `Name` or
41/// `Version` value, so the key round-trips unambiguously.
42pub fn type_key(name: &str, version: &str) -> String {
43 format!("{name}\u{1}{version}")
44}
45
46/// Split a [`type_key`] back into `(name, version)`.
47pub fn split_type_key(key: &str) -> Option<(&str, &str)> {
48 key.split_once('\u{1}')
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn type_key_round_trips() {
57 let k = type_key("send-email", "1.0");
58 assert_eq!(split_type_key(&k), Some(("send-email", "1.0")));
59 }
60
61 #[test]
62 fn domain_arn_shape() {
63 assert_eq!(
64 domain_arn("us-east-1", "000000000000", "orders"),
65 "arn:aws:swf:us-east-1:000000000000:/domain/orders"
66 );
67 }
68
69 #[test]
70 fn run_ids_are_unique_and_shaped() {
71 let a = new_run_id();
72 let b = new_run_id();
73 assert_ne!(a, b);
74 assert_eq!(a.len(), 64);
75 assert!(a.chars().all(|c| c.is_ascii_hexdigit()));
76 }
77}