rib/compiler/
worker_functions_in_rib.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{FunctionTypeRegistry, InferredExpr, RegistryKey, RegistryValue, RibError};
16use golem_wasm_ast::analysis::AnalysedType;
17
18// An easier data type that focus just on the side effecting function calls in Rib script.
19// These will not include variant or enum calls, that were originally
20// tagged as functions before compilation.
21// This is why we need a fully inferred Rib (fully compiled rib),
22// which has specific details, along with original type registry to construct this data.
23// These function calls are indeed worker invoke calls and nothing else.
24// If Rib has inbuilt function support, those will not be included here either.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct WorkerFunctionsInRib {
27    pub function_calls: Vec<WorkerFunctionType>,
28}
29
30impl WorkerFunctionsInRib {
31    pub fn from_inferred_expr(
32        inferred_expr: &InferredExpr,
33        original_type_registry: &FunctionTypeRegistry,
34    ) -> Result<Option<WorkerFunctionsInRib>, RibError> {
35        let worker_invoke_registry_keys = inferred_expr.worker_invoke_registry_keys();
36        let type_registry_subset =
37            original_type_registry.get_from_keys(worker_invoke_registry_keys);
38        let mut function_calls = vec![];
39
40        for (key, value) in type_registry_subset.types {
41            if let RegistryValue::Function {
42                parameter_types,
43                return_types,
44            } = value
45            {
46                let function_call_in_rib = WorkerFunctionType {
47                    function_key: key,
48                    parameter_types,
49                    return_types,
50                };
51                function_calls.push(function_call_in_rib)
52            } else {
53                return Err(RibError::InternalError(
54                    "function calls should have parameter types and return types".to_string(),
55                ));
56            }
57        }
58
59        if function_calls.is_empty() {
60            Ok(None)
61        } else {
62            Ok(Some(WorkerFunctionsInRib { function_calls }))
63        }
64    }
65}
66
67// The type of a function call with worker (ephmeral or durable) in Rib script
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct WorkerFunctionType {
70    pub function_key: RegistryKey,
71    pub parameter_types: Vec<AnalysedType>,
72    pub return_types: Vec<AnalysedType>,
73}
74
75#[cfg(feature = "protobuf")]
76mod protobuf {
77    use crate::{RegistryKey, WorkerFunctionType, WorkerFunctionsInRib};
78    use golem_api_grpc::proto::golem::rib::WorkerFunctionType as WorkerFunctionTypeProto;
79    use golem_api_grpc::proto::golem::rib::WorkerFunctionsInRib as WorkerFunctionsInRibProto;
80    use golem_wasm_ast::analysis::AnalysedType;
81
82    impl TryFrom<WorkerFunctionsInRibProto> for WorkerFunctionsInRib {
83        type Error = String;
84
85        fn try_from(value: WorkerFunctionsInRibProto) -> Result<Self, Self::Error> {
86            let function_calls_proto = value.function_calls;
87            let function_calls = function_calls_proto
88                .iter()
89                .map(|worker_function_type_proto| {
90                    WorkerFunctionType::try_from(worker_function_type_proto.clone())
91                })
92                .collect::<Result<_, _>>()?;
93            Ok(Self { function_calls })
94        }
95    }
96
97    impl From<WorkerFunctionsInRib> for WorkerFunctionsInRibProto {
98        fn from(value: WorkerFunctionsInRib) -> Self {
99            WorkerFunctionsInRibProto {
100                function_calls: value
101                    .function_calls
102                    .iter()
103                    .map(|x| WorkerFunctionTypeProto::from(x.clone()))
104                    .collect(),
105            }
106        }
107    }
108
109    impl TryFrom<WorkerFunctionTypeProto> for WorkerFunctionType {
110        type Error = String;
111
112        fn try_from(value: WorkerFunctionTypeProto) -> Result<Self, Self::Error> {
113            let return_types = value
114                .return_types
115                .iter()
116                .map(AnalysedType::try_from)
117                .collect::<Result<_, _>>()?;
118
119            let parameter_types = value
120                .parameter_types
121                .iter()
122                .map(AnalysedType::try_from)
123                .collect::<Result<_, _>>()?;
124
125            let registry_key_proto = value.function_key.ok_or("Function key missing")?;
126            let function_key = RegistryKey::try_from(registry_key_proto)?;
127
128            Ok(Self {
129                function_key,
130                return_types,
131                parameter_types,
132            })
133        }
134    }
135
136    impl From<WorkerFunctionType> for WorkerFunctionTypeProto {
137        fn from(value: WorkerFunctionType) -> Self {
138            let registry_key = (&value.function_key).into();
139
140            WorkerFunctionTypeProto {
141                function_key: Some(registry_key),
142                parameter_types: value
143                    .parameter_types
144                    .iter()
145                    .map(|analysed_type| analysed_type.into())
146                    .collect(),
147                return_types: value
148                    .return_types
149                    .iter()
150                    .map(|analysed_type| analysed_type.into())
151                    .collect(),
152            }
153        }
154    }
155}