Skip to content

Commit

Permalink
Reuse Template Service (#345)
Browse files Browse the repository at this point in the history
* base template service in progress

* reuse code from base, and simplify errors in template service
  • Loading branch information
nicoburniske authored Apr 2, 2024
1 parent 4efb355 commit c95f2cd
Show file tree
Hide file tree
Showing 20 changed files with 245 additions and 211 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"golem-common",
"golem-service-base",
"golem-template-compilation-service",
"golem-template-service-base",
"golem-template-service",
"golem-shard-manager",
"golem-worker-executor-base",
Expand Down Expand Up @@ -67,6 +68,7 @@ futures-util = "0.3.29"
golem-wasm-ast = "0.2.1"
golem-wasm-rpc = { version = "0.0.16", default-features = false, features = ["host"] }
http = "1.0.0" # keep in sync with wasmtime
http_02 = { package = "http", version = "0.2.11" }
humantime-serde = "1.1.1"
hyper = { version = "1.0.1", features = ["full"] } # keep in sync with wasmtime
iso8601-timestamp = "0.2.16"
Expand Down
2 changes: 1 addition & 1 deletion golem-service-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ aws-config = { workspace = true }
aws-sdk-s3 = { workspace = true }
bigdecimal = "0.4.2"
http = { workspace = true }
http_02 = { package = "http", version = "0.2.11" }
http_02 = { workspace = true }
hyper = { workspace = true }
num-traits = "0.2"
poem-openapi = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion golem-shard-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ figment = { workspace = true }
fred = { workspace = true }
futures = { workspace = true }
http = { workspace = true }
http_02 = { package = "http", version = "0.2.11" }
http_02 = { workspace = true }
humantime-serde = { workspace = true }
kube = { version = "0.88.1", features = ["client"], optional = true }
k8s-openapi = { version = "0.21.1", features = ["earliest"], optional = true }
Expand Down
2 changes: 1 addition & 1 deletion golem-template-compilation-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ golem-worker-executor-base = { version = "0.0.0", path = "../golem-worker-execut
async-trait = { workspace = true }
futures = { workspace = true }
http = { workspace = true }
http_02 = { package = "http", version = "0.2.11" }
http_02 = { workspace = true }
tokio = { workspace = true }

tracing = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion golem-template-compilation-service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl TemplateServiceConfig {
.authority(format!("{}:{}", self.host, self.port).as_str())
.path_and_query("/")
.build()
.expect("Failed to build TemplateServiceTemplateService URI")
.expect("Failed to build TemplateService URI")
}
}

Expand Down
17 changes: 17 additions & 0 deletions golem-template-service-base/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "golem-template-service-base"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-trait = { workspace = true }
golem-api-grpc = { path = "../golem-api-grpc", version = "0.0.0" }
golem-common = { path = "../golem-common", version = "0.0.0" }
golem-service-base = { path = "../golem-service-base" }
golem-wasm-ast = { workspace = true }
http_02 = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
27 changes: 27 additions & 0 deletions golem-template-service-base/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use serde::Deserialize;

#[derive(Clone, Debug, Deserialize)]
#[serde(tag = "type", content = "config")]
#[derive(Default)]
pub enum TemplateCompilationConfig {
Enabled(TemplateCompilationEnabledConfig),
#[default]
Disabled,
}

#[derive(Clone, Debug, Deserialize)]
pub struct TemplateCompilationEnabledConfig {
pub host: String,
pub port: u16,
}

impl TemplateCompilationEnabledConfig {
pub fn uri(&self) -> http_02::Uri {
http_02::Uri::builder()
.scheme("http")
.authority(format!("{}:{}", self.host, self.port).as_str())
.path_and_query("/")
.build()
.expect("Failed to build TemplateCompilationService URI")
}
}
2 changes: 2 additions & 0 deletions golem-template-service-base/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod config;
pub mod service;
2 changes: 2 additions & 0 deletions golem-template-service-base/src/service/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod template_compilation;
pub mod template_processor;
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ pub struct TemplateCompilationServiceDefault {
}

impl TemplateCompilationServiceDefault {
pub fn new(host: String, port: u16) -> Self {
let uri = format!("http://{}:{}", host, port)
.parse()
.expect("Failed to parse TemplateCompilationService URI");
pub fn new(uri: http_02::Uri) -> Self {
Self { uri }
}
}
Expand Down
89 changes: 89 additions & 0 deletions golem-template-service-base/src/service/template_processor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use std::fmt::{self, Display, Formatter};

use golem_service_base::model::TemplateMetadata;
use golem_wasm_ast::{
analysis::{AnalysedExport, AnalysedFunction, AnalysisContext, AnalysisFailure},
component::Component,
IgnoreAllButMetadata,
};

pub fn process_template(data: &[u8]) -> Result<TemplateMetadata, TemplateProcessingError> {
let component = Component::<IgnoreAllButMetadata>::from_bytes(data)
.map_err(TemplateProcessingError::Parsing)?;

let producers = component
.get_all_producers()
.into_iter()
.map(|producers| producers.into())
.collect::<Vec<_>>();

let state = AnalysisContext::new(component);

let mut exports = state
.get_top_level_exports()
.map_err(TemplateProcessingError::Analysis)?;

add_resource_drops(&mut exports);

let exports = exports
.into_iter()
.map(|export| export.into())
.collect::<Vec<_>>();

Ok(TemplateMetadata { exports, producers })
}

#[derive(Debug, thiserror::Error)]
pub enum TemplateProcessingError {
Parsing(String),
Analysis(AnalysisFailure),
}

impl Display for TemplateProcessingError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
TemplateProcessingError::Parsing(e) => write!(f, "Parsing error: {}", e),
TemplateProcessingError::Analysis(source) => {
let AnalysisFailure::Failed(error) = source;
write!(f, "Analysis error: {}", error)
}
}
}
}

fn add_resource_drops(exports: &mut Vec<AnalysedExport>) {
// Components are not exporting explicit drop functions for exported resources, but
// worker executor does. So we keep golem-wasm-ast as an universal library and extend
// its result with the explicit drops here, for each resource, identified by an exported
// constructor.

let mut to_add = Vec::new();
for export in exports.iter_mut() {
match export {
AnalysedExport::Function(fun) => {
if fun.is_constructor() {
let drop_name = fun.name.replace("[constructor]", "[drop]");
to_add.push(AnalysedExport::Function(AnalysedFunction {
name: drop_name,
..fun.clone()
}));
}
}
AnalysedExport::Instance(instance) => {
let mut to_add = Vec::new();
for fun in &instance.funcs {
if fun.is_constructor() {
let drop_name = fun.name.replace("[constructor]", "[drop]");
to_add.push(AnalysedFunction {
name: drop_name,
..fun.clone()
});
}
}
instance.funcs.extend(to_add.into_iter());
}
}
}

exports.extend(to_add);
}
5 changes: 4 additions & 1 deletion golem-template-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true }
uuid = { workspace = true }
humantime-serde = { workspace = true }
http_02 = { package = "http", version = "0.2.11" }
http_02 = { workspace = true }
golem-template-service-base = { version = "0.1.0", path = "../golem-template-service-base" }
thiserror.workspace = true
anyhow.workspace = true
41 changes: 15 additions & 26 deletions golem-template-service/src/api/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,44 +51,33 @@ pub struct UploadPayload {
type Result<T> = std::result::Result<T, TemplateError>;

impl From<TemplateServiceError> for TemplateError {
fn from(value: TemplateServiceError) -> Self {
match value {
TemplateServiceError::Internal(error) => {
TemplateError::InternalError(Json(ErrorBody { error }))
}
TemplateServiceError::TemplateProcessingError(error) => {
TemplateError::BadRequest(Json(ErrorsBody {
errors: vec![error],
}))
}
TemplateServiceError::UnknownTemplateId(_) => {
fn from(error: TemplateServiceError) -> Self {
match error {
TemplateServiceError::UnknownTemplateId(_)
| TemplateServiceError::UnknownVersionedTemplateId(_) => {
TemplateError::NotFound(Json(ErrorBody {
error: "Template not found".to_string(),
error: error.to_string(),
}))
}
TemplateServiceError::UnknownVersionedTemplateId(_) => {
TemplateError::NotFound(Json(ErrorBody {
error: "Template not found".to_string(),
TemplateServiceError::AlreadyExists(_) => {
TemplateError::AlreadyExists(Json(ErrorBody {
error: error.to_string(),
}))
}
TemplateServiceError::IOError(error) => {
TemplateError::InternalError(Json(ErrorBody { error }))
TemplateServiceError::Internal(error) => {
TemplateError::InternalError(Json(ErrorBody {
error: error.to_string(),
}))
}
TemplateServiceError::AlreadyExists(_) => {
TemplateError::AlreadyExists(Json(ErrorBody {
error: "Template already exists".to_string(),
TemplateServiceError::TemplateProcessingError(error) => {
TemplateError::BadRequest(Json(ErrorsBody {
errors: vec![error.to_string()],
}))
}
}
}
}

impl From<String> for TemplateError {
fn from(value: String) -> Self {
TemplateError::InternalError(Json(ErrorBody { error: value }))
}
}

impl From<ReadBodyError> for TemplateError {
fn from(value: ReadBodyError) -> Self {
TemplateError::InternalError(Json(ErrorBody {
Expand Down
18 changes: 1 addition & 17 deletions golem-template-service/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use figment::providers::{Env, Format, Toml};
use figment::Figment;
use golem_service_base::config::TemplateStoreConfig;
use golem_template_service_base::config::TemplateCompilationConfig;
use serde::Deserialize;
use std::time::Duration;

Expand Down Expand Up @@ -49,7 +50,6 @@ pub struct TemplateServiceConfig {
pub db: DbConfig,
pub template_store: TemplateStoreConfig,
pub compilation: TemplateCompilationConfig,
pub worker_executor_client_cache: WorkerExecutorClientCacheConfig,
}

#[derive(Clone, Debug, Deserialize)]
Expand Down Expand Up @@ -79,21 +79,6 @@ pub struct DbPostgresConfig {
pub schema: Option<String>,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(tag = "type", content = "config")]
#[derive(Default)]
pub enum TemplateCompilationConfig {
Enabled(TemplateCompilationEnabledConfig),
#[default]
Disabled,
}

#[derive(Clone, Debug, Deserialize)]
pub struct TemplateCompilationEnabledConfig {
pub host: String,
pub port: u16,
}

impl TemplateServiceConfig {
pub fn new() -> Self {
Figment::new()
Expand All @@ -114,7 +99,6 @@ impl Default for TemplateServiceConfig {
db: DbConfig::default(),
template_store: TemplateStoreConfig::default(),
compilation: TemplateCompilationConfig::default(),
worker_executor_client_cache: WorkerExecutorClientCacheConfig::default(),
}
}
}
Expand Down
Loading

0 comments on commit c95f2cd

Please sign in to comment.