Skip to content
This repository was archived by the owner on Aug 3, 2026. It is now read-only.

Commit 429ef1f

Browse files
committed
refactor: streamline action handling and improve queue management
Made-with: Cursor
1 parent 50e3507 commit 429ef1f

8 files changed

Lines changed: 179 additions & 152 deletions

File tree

reqactor/src/action.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ pub enum Action {
1717
impl Action {
1818
pub fn request_key(&self) -> &RequestKey {
1919
match self {
20-
Action::Prove { request_key, .. } => request_key,
21-
Action::Cancel { request_key, .. } => request_key,
20+
Action::Prove { request_key, .. } | Action::Cancel { request_key, .. } => request_key,
2221
}
2322
}
2423
}

reqactor/src/actor.rs

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{
22
collections::HashMap,
3-
// ops::DerefMut,
43
sync::{
54
atomic::{AtomicBool, Ordering},
65
Arc,
@@ -124,43 +123,56 @@ impl Actor {
124123
) -> Result<StatusWithContext, String> {
125124
let pool_status_opt = self.pool_get_status(&request_key).await?;
126125

127-
// Return successful status if the request is already succeeded
128-
if matches!(
129-
pool_status_opt.as_ref().map(|s| s.status()),
130-
Some(Status::Success { .. })
131-
) {
126+
if pool_status_opt
127+
.as_ref()
128+
.is_some_and(|s| matches!(s.status(), Status::Success { .. }))
129+
{
132130
return Ok(pool_status_opt.unwrap());
133131
}
134132

135-
// Mark the request as registered in the pool
136133
let status = StatusWithContext::new(Status::Registered, start_time);
137-
if pool_status_opt.is_none() {
138-
self.pool_add_new(request_key.clone(), request_entity.clone(), status.clone())
139-
.await?;
140-
} else {
141-
self.pool_update_status(request_key.clone(), status.clone())
142-
.await?;
143-
}
134+
self.ensure_pool_registered(&request_key, &request_entity, &status, pool_status_opt.is_none())
135+
.await?;
136+
137+
let queue_result = {
138+
let mut queue = self.queue.lock().await;
139+
if queue.contains(&request_key) {
140+
Ok(())
141+
} else {
142+
queue.add_pending(request_key.clone(), request_entity)
143+
}
144+
};
144145

145-
// Push the request into the queue and notify to start the action
146-
let mut queue = self.queue.lock().await;
147-
if !queue.contains(&request_key) {
148-
match queue.add_pending(request_key.clone(), request_entity) {
149-
Ok(()) => {
150-
self.notify.notify_one();
151-
}
152-
Err(error_msg) => {
153-
// If queue is at capacity, update the status to Failed
154-
let failed_status =
155-
StatusWithContext::new(Status::Failed { error: error_msg }, start_time);
156-
self.pool_update_status(request_key.clone(), failed_status.clone())
157-
.await?;
158-
return Ok(failed_status);
159-
}
146+
match queue_result {
147+
Ok(()) => {
148+
self.notify.notify_one();
149+
Ok(status)
150+
}
151+
Err(error_msg) => {
152+
let failed_status =
153+
StatusWithContext::new(Status::Failed { error: error_msg }, start_time);
154+
self.pool_update_status(request_key, failed_status.clone())
155+
.await?;
156+
Ok(failed_status)
160157
}
161158
}
159+
}
162160

163-
return Ok(status);
161+
/// Add or update pool entry so the request is marked as Registered.
162+
async fn ensure_pool_registered(
163+
&self,
164+
request_key: &RequestKey,
165+
request_entity: &RequestEntity,
166+
status: &StatusWithContext,
167+
is_new: bool,
168+
) -> Result<(), String> {
169+
if is_new {
170+
self.pool_add_new(request_key.clone(), request_entity.clone(), status.clone())
171+
.await
172+
} else {
173+
self.pool_update_status(request_key.clone(), status.clone())
174+
.await
175+
}
164176
}
165177

166178
pub async fn pause(&self) -> Result<(), String> {

reqactor/src/backend.rs

Lines changed: 57 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -95,49 +95,14 @@ impl Backend {
9595
let handle = tokio::spawn(async move {
9696
let _permit = permit;
9797

98-
let result = match request_entity {
99-
RequestEntity::SingleProof(_)
100-
| RequestEntity::Aggregation(_)
101-
| RequestEntity::BatchProof(_)
102-
| RequestEntity::GuestInput(_)
103-
| RequestEntity::BatchGuestInput(_) => Err(
104-
"legacy single-block and batch proving are removed; use Shasta only"
105-
.to_string(),
106-
),
107-
RequestEntity::ShastaGuestInput(entity) => {
108-
do_generate_shasta_proposal_guest_input(
109-
&mut pool_,
110-
&chain_specs,
111-
request_key_.clone(),
112-
entity,
113-
)
114-
.await
115-
}
116-
RequestEntity::ShastaProof(entity) => {
117-
do_prove_shasta_proposal(
118-
&mut pool_,
119-
&chain_specs,
120-
request_key_.clone(),
121-
entity,
122-
)
123-
.await
124-
}
125-
RequestEntity::ShastaAggregation(entity) => {
126-
do_shasta_aggregation(&mut pool_, request_key_.clone(), entity).await
127-
}
128-
};
129-
let status = match result {
130-
Ok(proof) => {
131-
let proof_str = format!("{}", proof);
132-
tracing::info!(
133-
"Actor Backend successfully proved {request_key_}. Proof: {proof_str}"
134-
);
135-
Status::Success { proof }
136-
}
137-
Err(e) => Status::Failed {
138-
error: e.to_string(),
139-
},
140-
};
98+
let result = dispatch_proof_request(
99+
&mut pool_,
100+
&chain_specs,
101+
request_key_.clone(),
102+
request_entity,
103+
)
104+
.await;
105+
let status = result_to_status(&result, &request_key_);
141106
let _ = pool_.update_status(
142107
request_key_.clone(),
143108
StatusWithContext::new(status, chrono::Utc::now()),
@@ -151,19 +116,62 @@ impl Backend {
151116
tokio::spawn(async move {
152117
if let Err(e) = handle.await {
153118
tracing::error!("Actor thread errored while proving {request_key}: {e:?}");
154-
let status = Status::Failed {
155-
error: e.to_string(),
156-
};
157-
let _ = pool_.update_status(request_key.clone(), status.clone().into());
119+
let status =
120+
StatusWithContext::new(Status::Failed { error: e.to_string() }, chrono::Utc::now());
121+
let _ = pool_.update_status(request_key.clone(), status);
158122
}
159-
160-
let _res = done_tx_.send(request_key.clone()).await;
123+
let _ = done_tx_.send(request_key).await;
161124
notifier_.notify_one();
162125
});
163126
}
164127
}
165128
}
166129

130+
/// Dispatches the request to the appropriate proof handler.
131+
async fn dispatch_proof_request(
132+
pool: &mut Pool,
133+
chain_specs: &SupportedChainSpecs,
134+
request_key: RequestKey,
135+
request_entity: RequestEntity,
136+
) -> Result<raiko_lib::prover::Proof, String> {
137+
match request_entity {
138+
RequestEntity::SingleProof(_)
139+
| RequestEntity::Aggregation(_)
140+
| RequestEntity::BatchProof(_)
141+
| RequestEntity::GuestInput(_)
142+
| RequestEntity::BatchGuestInput(_) => Err(
143+
"legacy single-block and batch proving are removed; use Shasta only".to_string(),
144+
),
145+
RequestEntity::ShastaGuestInput(entity) => {
146+
do_generate_shasta_proposal_guest_input(pool, chain_specs, request_key, entity).await
147+
}
148+
RequestEntity::ShastaProof(entity) => {
149+
do_prove_shasta_proposal(pool, chain_specs, request_key, entity).await
150+
}
151+
RequestEntity::ShastaAggregation(entity) => {
152+
do_shasta_aggregation(pool, request_key, entity).await
153+
}
154+
}
155+
}
156+
157+
/// Converts proof result to pool status.
158+
fn result_to_status(
159+
result: &Result<raiko_lib::prover::Proof, String>,
160+
request_key: &RequestKey,
161+
) -> Status {
162+
match result {
163+
Ok(proof) => {
164+
tracing::info!("Actor Backend successfully proved {request_key}. Proof: {proof}");
165+
Status::Success {
166+
proof: proof.clone(),
167+
}
168+
}
169+
Err(e) => Status::Failed {
170+
error: e.clone(),
171+
},
172+
}
173+
}
174+
167175
async fn do_shasta_aggregation(
168176
pool: &mut dyn IdWrite,
169177
request_key: RequestKey,

reqactor/src/queue.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -49,39 +49,44 @@ impl Queue {
4949
request_key: RequestKey,
5050
request_entity: RequestEntity,
5151
) -> Result<(), String> {
52-
// Check if queue is at capacity
5352
if self.is_at_capacity() {
5453
return Err("Reached the maximum queue size, please try again later".to_string());
5554
}
5655

57-
if self.queued_keys.insert(request_key.clone()) {
58-
// Check priority and add to appropriate queue using pattern matching
59-
match &request_key {
60-
RequestKey::Aggregation(_) => {
61-
tracing::info!("Adding aggregation request to high priority queue");
62-
self.agg_queue.push_back((request_key, request_entity));
63-
}
64-
RequestKey::BatchProof(_) => {
65-
tracing::info!("Adding batch proof request to medium priority queue");
66-
self.batch_queue.push_back((request_key, request_entity));
67-
}
68-
_ => {
69-
self.preflight_queue
70-
.push_back((request_key, request_entity));
71-
}
72-
}
56+
if !self.queued_keys.insert(request_key.clone()) {
57+
return Ok(());
7358
}
59+
60+
let queue = self.priority_queue_for(&request_key);
61+
queue.push_back((request_key, request_entity));
7462
Ok(())
7563
}
7664

77-
/// Attempts to move a request from either the high, medium or low priority queue into the in-flight set
78-
/// and starts processing it. High priority requests are processed first.
65+
/// Returns the appropriate queue for the given request key (agg > batch > preflight).
66+
fn priority_queue_for(
67+
&mut self,
68+
request_key: &RequestKey,
69+
) -> &mut VecDeque<(RequestKey, RequestEntity)> {
70+
match request_key {
71+
RequestKey::Aggregation(_) => {
72+
tracing::info!("Adding aggregation request to high priority queue");
73+
&mut self.agg_queue
74+
}
75+
RequestKey::BatchProof(_) => {
76+
tracing::info!("Adding batch proof request to medium priority queue");
77+
&mut self.batch_queue
78+
}
79+
_ => &mut self.preflight_queue,
80+
}
81+
}
82+
83+
/// Pops the next request (agg > batch > preflight) and marks it in-progress.
7984
pub fn try_next(&mut self) -> Option<(RequestKey, RequestEntity)> {
80-
let (request_key, request_entity) = self.agg_queue.pop_front().or_else(|| {
81-
self.batch_queue
82-
.pop_front()
83-
.or_else(|| self.preflight_queue.pop_front())
84-
})?;
85+
let (request_key, request_entity) = self
86+
.agg_queue
87+
.pop_front()
88+
.or_else(|| self.batch_queue.pop_front())
89+
.or_else(|| self.preflight_queue.pop_front())?;
8590

8691
self.working_in_progress.insert(request_key.clone());
8792
Some((request_key, request_entity))

reqpool/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use serde::{Deserialize, Serialize};
22

3+
/// Configuration for the request pool (Redis or in-memory backend).
34
#[derive(Debug, Clone, Serialize, Deserialize)]
4-
/// The configuration for the redis-backend request pool
55
pub struct RedisPoolConfig {
66
/// The URL of the Redis database, e.g. "redis://localhost:6379"
77
pub redis_url: String,

reqpool/src/memory_backend.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ use lru::LruCache;
1414
type SingleStorage = Arc<Mutex<LruCache<Value, Value>>>;
1515
type GlobalStorage = Mutex<HashMap<String, SingleStorage>>;
1616

17+
const DEFAULT_MEMORY_BACKEND_CAPACITY: usize = 512;
18+
19+
fn parse_memory_backend_capacity() -> usize {
20+
std::env::var("MEMORY_BACKEND_SIZE")
21+
.ok()
22+
.and_then(|s| s.parse().ok())
23+
.unwrap_or(DEFAULT_MEMORY_BACKEND_CAPACITY)
24+
}
25+
1726
lazy_static! {
1827
// #{redis_url => single_storage}
1928
//
@@ -29,17 +38,13 @@ pub struct MemoryBackend {
2938
impl MemoryBackend {
3039
pub fn new(redis_url: String) -> Self {
3140
let mut global = GLOBAL_STORAGE.lock().unwrap();
32-
33-
let mem_capacity = std::env::var("MEMORY_BACKEND_SIZE")
34-
.unwrap_or("2048".to_string())
35-
.parse::<usize>()
36-
.unwrap_or_else(|_| 2048);
41+
let capacity = parse_memory_backend_capacity();
3742
Self {
3843
storage: global
3944
.entry(redis_url)
4045
.or_insert_with(|| {
4146
Arc::new(Mutex::new(LruCache::new(
42-
NonZeroUsize::new(mem_capacity).unwrap(),
47+
NonZeroUsize::new(capacity).unwrap(),
4348
)))
4449
})
4550
.clone(),

0 commit comments

Comments
 (0)