ave_core/evaluation/compiler/
temp_compiler.rs1use std::path::PathBuf;
2use std::time::Instant;
3
4use async_trait::async_trait;
5use ave_actors::{
6 Actor, ActorContext, ActorError, ActorPath, Handler, Message,
7 NotPersistentActor,
8};
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11use tokio::fs;
12use tracing::{Span, error, info_span};
13
14use ave_common::identity::HashAlgorithm;
15
16use super::{CompilerResponse, CompilerSupport};
17use crate::metrics::try_core_metrics;
18
19#[derive(Clone, Debug, Serialize, Deserialize)]
20pub struct TempCompiler {
21 hash: HashAlgorithm,
22}
23
24impl TempCompiler {
25 pub const fn new(hash: HashAlgorithm) -> Self {
26 Self { hash }
27 }
28}
29
30#[derive(Debug, Clone)]
31pub enum TempCompilerMessage {
32 Compile {
33 contract: String,
34 contract_name: String,
35 initial_value: Value,
36 contract_path: PathBuf,
37 },
38}
39
40impl Message for TempCompilerMessage {}
41
42impl NotPersistentActor for TempCompiler {}
43
44#[async_trait]
45impl Actor for TempCompiler {
46 type Event = ();
47 type Message = TempCompilerMessage;
48 type Response = CompilerResponse;
49
50 fn get_span(id: &str, parent_span: Option<Span>) -> tracing::Span {
51 parent_span.map_or_else(
52 || info_span!("TempCompiler", id),
53 |parent_span| info_span!(parent: parent_span, "TempCompiler", id),
54 )
55 }
56}
57
58#[async_trait]
59impl Handler<Self> for TempCompiler {
60 async fn handle_message(
61 &mut self,
62 _sender: ActorPath,
63 msg: TempCompilerMessage,
64 ctx: &mut ActorContext<Self>,
65 ) -> Result<CompilerResponse, ActorError> {
66 match msg {
67 TempCompilerMessage::Compile {
68 contract,
69 contract_name,
70 initial_value,
71 contract_path,
72 } => {
73 let started_at = Instant::now();
74 let _ = fs::remove_dir_all(&contract_path).await;
75 if let Err(e) = CompilerSupport::compile_fresh(
76 self.hash,
77 ctx,
78 &contract,
79 &contract_path,
80 initial_value,
81 )
82 .await
83 {
84 if let Some(metrics) = try_core_metrics() {
85 metrics.observe_contract_prepare(
86 "temporary",
87 "error",
88 started_at.elapsed(),
89 );
90 }
91 error!(
92 msg_type = "Compile",
93 error = %e,
94 contract_name = %contract_name,
95 path = %contract_path.display(),
96 "Temporary contract compilation or validation failed"
97 );
98 let _ = fs::remove_dir_all(&contract_path).await;
99 return Ok(CompilerResponse::Error(e));
100 }
101
102 if let Some(metrics) = try_core_metrics() {
103 metrics.observe_contract_prepare(
104 "temporary",
105 "recompiled",
106 started_at.elapsed(),
107 );
108 }
109
110 if let Err(e) = fs::remove_dir_all(&contract_path).await {
111 error!(
112 msg_type = "Compile",
113 error = %e,
114 path = %contract_path.display(),
115 "Failed to remove temporal contract directory"
116 );
117 }
118
119 Ok(CompilerResponse::Ok)
120 }
121 }
122 }
123}