greentic_runner_host/engine/
host.rs1use super::error::GResult;
2use async_trait::async_trait;
3use greentic_types::TenantCtx;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::HashMap;
7use std::hash::{Hash, Hasher};
8use std::sync::Arc;
9use std::time::{Duration, SystemTime};
10
11#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
12pub struct SpanContext {
13 pub trace_id: Option<String>,
14 pub span_id: Option<String>,
15}
16
17#[async_trait]
18pub trait SecretsHost: Send + Sync {
19 async fn get(&self, name: &str) -> GResult<String>;
20}
21
22#[async_trait]
23pub trait TelemetryHost: Send + Sync {
24 async fn emit(&self, span: &SpanContext, fields: &[(&str, &str)]) -> GResult<()>;
25}
26
27#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
28pub struct SessionKey {
29 pub tenant_key: String,
30 pub flow_id: String,
31 pub session_hint: Option<String>,
32}
33
34impl SessionKey {
35 pub fn new(tenant: &TenantCtx, flow_id: &str, session_hint: Option<String>) -> Self {
36 let tenant_key = format!("{}::{}", tenant.env.as_str(), tenant.tenant.as_str());
37 Self {
38 tenant_key,
39 flow_id: flow_id.to_string(),
40 session_hint,
41 }
42 }
43
44 pub fn stable_session_id(&self) -> Option<String> {
45 self.session_hint.clone()
46 }
47}
48
49#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
50pub struct SessionCursor {
51 pub position: usize,
52 pub outbox_seq: u64,
53}
54
55#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
56pub struct SessionOutboxEntry {
57 pub seq: u64,
58 pub hash: String,
59 pub response: Value,
60}
61
62#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
63pub struct WaitState {
64 pub reason: String,
65 pub recorded_at: SystemTime,
66}
67
68#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
69pub struct SessionSnapshot {
70 pub key: SessionKey,
71 pub session_id: String,
72 pub revision: u64,
73 pub cursor: SessionCursor,
74 pub state: Value,
75 pub outbox: HashMap<OutboxKey, SessionOutboxEntry>,
76 pub waiting: Option<WaitState>,
77 pub last_outcome: Option<Value>,
78 pub ttl: Duration,
79}
80
81impl SessionSnapshot {
82 pub fn new(key: SessionKey, session_id: String) -> Self {
83 Self {
84 key,
85 session_id,
86 revision: 0,
87 cursor: SessionCursor::default(),
88 state: Value::Object(Default::default()),
89 outbox: HashMap::new(),
90 waiting: None,
91 last_outcome: None,
92 ttl: Duration::from_secs(3600),
93 }
94 }
95}
96
97#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
98pub struct OutboxKey {
99 seq: u64,
100 hash: String,
101}
102
103impl OutboxKey {
104 pub fn new(seq: u64, hash: String) -> Self {
105 Self { seq, hash }
106 }
107}
108
109impl Hash for OutboxKey {
110 fn hash<H: Hasher>(&self, state: &mut H) {
111 self.seq.hash(state);
112 self.hash.hash(state);
113 }
114}
115
116#[async_trait]
117pub trait SessionHost: Send + Sync {
118 async fn get(&self, key: &SessionKey) -> GResult<Option<SessionSnapshot>>;
119 async fn put(&self, snapshot: SessionSnapshot) -> GResult<()>;
120 async fn update_cas(&self, snapshot: SessionSnapshot, expected_revision: u64) -> GResult<bool>;
121 async fn delete(&self, key: &SessionKey) -> GResult<()>;
122 async fn touch(&self, key: &SessionKey, ttl: Duration) -> GResult<()>;
123}
124
125#[async_trait]
126pub trait StateHost: Send + Sync {
127 async fn get_json(&self, key: &SessionKey) -> GResult<Option<Value>>;
128 async fn set_json(&self, key: &SessionKey, value: Value) -> GResult<()>;
129 async fn del(&self, key: &SessionKey) -> GResult<()>;
130 async fn del_prefix(&self, key_prefix: &str) -> GResult<()>;
131}
132
133pub struct HostBundle {
134 pub secrets: Arc<dyn SecretsHost>,
135 pub telemetry: Arc<dyn TelemetryHost>,
136 pub session: Arc<dyn SessionHost>,
137 pub state: Arc<dyn StateHost>,
138}
139
140impl HostBundle {
141 pub fn new(
142 secrets: Arc<dyn SecretsHost>,
143 telemetry: Arc<dyn TelemetryHost>,
144 session: Arc<dyn SessionHost>,
145 state: Arc<dyn StateHost>,
146 ) -> Self {
147 Self {
148 secrets,
149 telemetry,
150 session,
151 state,
152 }
153 }
154}