Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ApiDefinition concept generic #342

Merged
merged 40 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8adfa48
Make the concept of ApiDefinition generic
afsalthaj Mar 31, 2024
109f8e2
Move validator to generic
afsalthaj Mar 31, 2024
083a9ac
make golem worker binding a generic idea
afsalthaj Mar 31, 2024
8c3f274
Start moving everything to an expression module
afsalthaj Mar 31, 2024
c9d6876
Start introducing more modules
afsalthaj Mar 31, 2024
5257a7b
Start compiling
afsalthaj Mar 31, 2024
8c9a8dd
Initial draft of code organisation
afsalthaj Mar 31, 2024
bd22746
Fix errors
afsalthaj Mar 31, 2024
62c96fa
Fix errors
afsalthaj Mar 31, 2024
403a6be
Fix errors
afsalthaj Mar 31, 2024
a88f93e
Add constraints
afsalthaj Mar 31, 2024
9ca9cce
Use Has patterns to support generic
afsalthaj Mar 31, 2024
086fa89
Response binding
afsalthaj Mar 31, 2024
0ec8ba2
First compiled version of draft
afsalthaj Apr 1, 2024
fe9356a
Optimise imports
afsalthaj Apr 1, 2024
9c3e6bb
Make modules private and use pub for crate
afsalthaj Apr 1, 2024
9e61961
Tighten privacy in every module
afsalthaj Apr 1, 2024
efae2ec
Avoid leaking Response mapping outside base module
afsalthaj Apr 1, 2024
683121d
Move internal logic to internal module
afsalthaj Apr 1, 2024
6d159dc
make sure to use mod internal pattern
afsalthaj Apr 1, 2024
062ab5f
Refactor oas_worker_bridge
afsalthaj Apr 1, 2024
afc96c0
Further maximise private modules
afsalthaj Apr 1, 2024
a902f8d
Try to compile golem worker service
afsalthaj Apr 1, 2024
cffc0d3
Fix errors
afsalthaj Apr 1, 2024
292b90c
Fix all compile time errors
afsalthaj Apr 1, 2024
4196b04
Compile everything
afsalthaj Apr 1, 2024
3805fae
Make sure everything compile
afsalthaj Apr 1, 2024
b76a65e
Fix clippy
afsalthaj Apr 1, 2024
4aa9218
Remove unused trait
afsalthaj Apr 1, 2024
4ab73fe
Fix more errors
afsalthaj Apr 1, 2024
76f4893
Fix more errors
afsalthaj Apr 2, 2024
bb3b0f8
Rename
afsalthaj Apr 2, 2024
18bdad3
Rearrange further
afsalthaj Apr 2, 2024
d262d2d
Reorganise code
afsalthaj Apr 2, 2024
2a43c9c
Reformat and rename service
afsalthaj Apr 2, 2024
a9de472
Fix clippy
afsalthaj Apr 2, 2024
0abcc30
Reformat and clippy for worker-service
afsalthaj Apr 2, 2024
322a093
Fix formatting
afsalthaj Apr 2, 2024
d2cb468
Fix worker service test
afsalthaj Apr 2, 2024
0942783
Delete commented code
afsalthaj Apr 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion golem-service-base/src/type_inference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ mod tests {
assert_eq!(infer_analysed_type(&value), AnalysedType::Record(vec![]));

let value = Value::Null;
assert_eq!(infer_analysed_type(&value), AnalysedType::Option(Box::new(AnalysedType::Str)));
assert_eq!(
infer_analysed_type(&value),
AnalysedType::Option(Box::new(AnalysedType::Str))
);

let mut map = serde_json::map::Map::new();
map.insert("ok".to_string(), Value::String("hello".to_string()));
Expand Down
38 changes: 18 additions & 20 deletions golem-worker-service-base/src/api/common.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use std::fmt::Display;

use golem_common::model::TemplateId;
use poem_openapi::payload::Json;
use poem_openapi::{ApiResponse, Object, Union};
use serde::{Deserialize, Serialize};

use crate::api_definition::MethodPattern;
use crate::service::http::http_api_definition_validator::RouteValidationError;

#[derive(Union)]
#[oai(discriminator_name = "type", one_of = true)]
Expand Down Expand Up @@ -36,14 +34,6 @@ pub struct MessageBody {
message: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Object)]
pub struct RouteValidationError {
pub method: MethodPattern,
pub path: String,
pub template: TemplateId,
pub detail: String,
}

#[derive(ApiResponse)]
pub enum ApiEndpointError {
#[oai(status = 400)]
Expand Down Expand Up @@ -101,15 +91,15 @@ impl ApiEndpointError {
mod conversion {
use poem_openapi::payload::Json;

use super::{
ApiEndpointError, RouteValidationError, ValidationErrorsBody, WorkerServiceErrorsBody,
};
use crate::api_definition_repo::ApiRegistrationRepoError;
use crate::repo::api_definition_repo::ApiRegistrationRepoError;
use crate::service::api_definition::ApiRegistrationError;
use crate::service::api_definition_validator::ValidationError;
use crate::service::api_definition_validator::ValidationErrors;
use crate::service::http::http_api_definition_validator::RouteValidationError;

use super::{ApiEndpointError, ValidationErrorsBody, WorkerServiceErrorsBody};

impl From<ApiRegistrationError> for ApiEndpointError {
fn from(error: ApiRegistrationError) -> Self {
impl From<ApiRegistrationError<RouteValidationError>> for ApiEndpointError {
fn from(error: ApiRegistrationError<RouteValidationError>) -> Self {
match error {
ApiRegistrationError::RepoError(error) => match error {
ApiRegistrationRepoError::AlreadyExists(_) => {
Expand All @@ -118,12 +108,20 @@ mod conversion {
ApiRegistrationRepoError::InternalError(_) => ApiEndpointError::internal(error),
},
ApiRegistrationError::ValidationError(e) => e.into(),
ApiRegistrationError::TemplateNotFoundError(template_id) => {
let templates = template_id
.iter()
.map(|t| t.to_string())
.collect::<Vec<String>>()
.join(", ");
ApiEndpointError::bad_request(format!("Templates not found, {}", templates))
}
}
}
}

impl From<ValidationError> for ApiEndpointError {
fn from(error: ValidationError) -> Self {
impl From<ValidationErrors<RouteValidationError>> for ApiEndpointError {
fn from(error: ValidationErrors<RouteValidationError>) -> Self {
let error = WorkerServiceErrorsBody::Validation(ValidationErrorsBody {
errors: error
.errors
Expand Down
64 changes: 42 additions & 22 deletions golem-worker-service-base/src/api/custom_http_request_api.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
use std::sync::Arc;

use crate::api_definition::ResponseMapping;
use crate::api_definition::http::HttpApiDefinition;
use async_trait::async_trait;
use hyper::header::HOST;
use poem::http::StatusCode;
use poem::{Body, Endpoint, Request, Response};
use tracing::{error, info};

use crate::api_request_route_resolver::WorkerBindingResolver;
use crate::http_request::{ApiInputPath, InputHttpRequest};
use crate::service::http_request_definition_lookup::HttpRequestDefinitionLookup;
use crate::worker_request::WorkerRequest;
use crate::worker_request_to_response::WorkerRequestToResponse;
use crate::http::{ApiInputPath, InputHttpRequest};
use crate::service::api_definition_lookup::ApiDefinitionLookup;

use crate::worker_binding::WorkerBindingResolver;
use crate::worker_bridge_execution::WorkerRequest;
use crate::worker_bridge_execution::WorkerRequestExecutor;

// Executes custom request with the help of worker_request_executor and definition_service
// This is a common API projects can make use of, similar to healthcheck service
#[derive(Clone)]
pub struct CustomHttpRequestApi {
pub worker_to_http_response_service:
Arc<dyn WorkerRequestToResponse<ResponseMapping, Response> + Sync + Send>,
pub api_definition_lookup_service: Arc<dyn HttpRequestDefinitionLookup + Sync + Send>,
pub worker_to_http_response_service: Arc<dyn WorkerRequestExecutor<Response> + Sync + Send>,
pub api_definition_lookup_service:
Arc<dyn ApiDefinitionLookup<InputHttpRequest, HttpApiDefinition> + Sync + Send>,
}

impl CustomHttpRequestApi {
pub fn new(
worker_to_http_response_service: Arc<
dyn WorkerRequestToResponse<ResponseMapping, Response> + Sync + Send,
worker_to_http_response_service: Arc<dyn WorkerRequestExecutor<Response> + Sync + Send>,
api_definition_lookup_service: Arc<
dyn ApiDefinitionLookup<InputHttpRequest, HttpApiDefinition> + Sync + Send,
>,
api_definition_lookup_service: Arc<dyn HttpRequestDefinitionLookup + Sync + Send>,
) -> Self {
Self {
worker_to_http_response_service,
Expand Down Expand Up @@ -67,15 +68,19 @@ impl CustomHttpRequestApi {

let api_request = InputHttpRequest {
input_path: ApiInputPath {
base_path: uri.path(),
query_path: uri.query(),
base_path: uri.path().to_string(),
query_path: uri.query().map(|x| x.to_string()),
},
headers: &headers,
req_method: &req_parts.method,
headers,
req_method: req_parts.method,
req_body: json_request_body,
};

let api_definition = match self.api_definition_lookup_service.get(&api_request).await {
let api_definition = match self
.api_definition_lookup_service
.get(api_request.clone())
.await
{
Ok(api_definition) => api_definition,
Err(err) => {
error!("API request host: {} - error: {}", host, err);
Expand Down Expand Up @@ -104,13 +109,28 @@ impl CustomHttpRequestApi {
};

// Execute the request using a executor
self.worker_to_http_response_service
.execute(
resolved_worker_request.clone(),
match self
.worker_to_http_response_service
.execute(resolved_worker_request.clone())
.await
{
Ok(worker_response) => worker_response.to_http_response(
&resolved_route.resolved_worker_binding_template.response,
&resolved_route.typed_value_from_input,
)
.await
),

Err(e) => {
error!(
"API request id: {} - request error: {}",
&api_definition.id, e
);
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Body::from_string(
format!("API request error {}", e).to_string(),
))
}
}
}

None => {
Expand Down
8 changes: 5 additions & 3 deletions golem-worker-service-base/src/api/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use crate::service::template::TemplateServiceError;
use crate::service::worker::WorkerServiceError;
use golem_service_base::model::*;
use poem_openapi::payload::Json;
use poem_openapi::*;
use tonic::Status;

use golem_service_base::model::*;

use crate::service::template::TemplateServiceError;
use crate::service::worker::WorkerServiceError;

// The dependents og golem-worker-service-base
// is expected to exposer worker api endpoints
// that can rely on WorkerApiBaseError
Expand Down
17 changes: 12 additions & 5 deletions golem-worker-service-base/src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
pub mod common;
pub mod custom_http_request_api;
pub mod error;
pub mod healthcheck;
pub mod register_api_definition_api;
pub use common::*;
pub use custom_http_request_api::*;
pub use error::*;
pub use healthcheck::*;
pub use register_api_definition_api::*;

// Components and request data that can be reused for implementing server API endpoints
mod common;
mod custom_http_request_api;
mod error;
mod healthcheck;
mod register_api_definition_api;
Loading
Loading