Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e9ec0a8
Migrate integration and provider HTTP types
prk-Jr Apr 9, 2026
d2fa12d
Merge branch 'feature/edgezero-pr12-handler-layer-types' into feature…
prk-Jr Apr 10, 2026
442a6e2
Resolve PR findings
prk-Jr Apr 10, 2026
0db7beb
Resolve PR findings
prk-Jr Apr 10, 2026
5dbbfb0
Merge feature/edgezero-pr12-handler-layer-types
prk-Jr Apr 16, 2026
94ec947
Address review findings: safe body reads and bounded inbound forwarding
prk-Jr Apr 16, 2026
6d9d96a
Merge feature/edgezero-pr12-handler-layer-types: resolve body-cap and…
prk-Jr Apr 21, 2026
4b27087
Address PR review: fmt, testlight body cap, auction constant, stale R…
prk-Jr Apr 21, 2026
a2036eb
Merge branch 'feature/edgezero-pr12-handler-layer-types' into feature…
prk-Jr Apr 27, 2026
86bd21e
Resolve PR review findings
prk-Jr Apr 30, 2026
9694980
Merge branch 'feature/edgezero-pr12-handler-layer-types' into feature…
prk-Jr Apr 30, 2026
bf31cca
Resolve PR 626 review findings
prk-Jr May 12, 2026
f360b82
Apply cargo fmt formatting
prk-Jr May 12, 2026
28205a0
Merge feature/edgezero-pr12-handler-layer-types into PR13
prk-Jr May 12, 2026
f551544
Resolve PR 626 round-1 review findings
prk-Jr May 28, 2026
2b17d4c
Merge feature/edgezero-pr12-handler-layer-types into PR13
prk-Jr May 28, 2026
936e721
Resolve merge conflicts from feature/edgezero-pr12-handler-layer-types
prk-Jr Jun 8, 2026
b71da80
Resolve PR 626 round-2 review findings
prk-Jr Jun 8, 2026
609154e
Merge remote-tracking branch 'origin/feature/edgezero-pr12-handler-la…
prk-Jr Jun 15, 2026
4d57b83
Give auction transport failures a consistent error envelope
prk-Jr Jun 15, 2026
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
6 changes: 2 additions & 4 deletions crates/trusted-server-adapter-fastly/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,6 @@ async fn route_request(
false,
),
(m, path) if integration_registry.has_route(&m, path) => {
let fastly_req = compat::to_fastly_request(req);
let result = integration_registry
.handle_proxy(ProxyDispatchInput {
method: &m,
Expand All @@ -599,15 +598,14 @@ async fn route_request(
kv: kv_graph.as_ref(),
ec_context: &mut ec_context,
services: runtime_services,
req: fastly_req,
req,
})
.await
.unwrap_or_else(|| {
Err(Report::new(TrustedServerError::BadRequest {
message: format!("Unknown integration route: {path}"),
}))
})
.map(compat::from_fastly_response);
});
(result, true)
}

Expand Down
22 changes: 17 additions & 5 deletions crates/trusted-server-adapter-fastly/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ impl PlatformHttpClient for FastlyPlatformHttpClient {
.map(PlatformPendingRequest::new)
.collect();

let ready = match result {
let (ready, failed_backend_name) = match result {
Ok(fastly_resp) => {
let backend_name = fastly_resp
.get_backend_name()
Expand All @@ -500,15 +500,27 @@ impl PlatformHttpClient for FastlyPlatformHttpClient {
""
})
.to_string();
fastly_response_to_platform(fastly_resp, backend_name, false)
(
fastly_response_to_platform(fastly_resp, backend_name, false),
None,
)
}
Err(e) => {
Err(Report::new(PlatformError::HttpClient)
.attach(format!("fastly select error: {e}")))
let failed_name = e.backend_name().to_string();
(
Err(Report::new(PlatformError::HttpClient).attach(format!(
"fastly select error for backend '{failed_name}': {e}"
))),
Some(failed_name),
)
}
};

Ok(PlatformSelectResult { ready, remaining })
Ok(PlatformSelectResult {
ready,
remaining,
failed_backend_name,
})
}
}

Expand Down
10 changes: 5 additions & 5 deletions crates/trusted-server-adapter-fastly/src/route_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use edgezero_core::body::Body as EdgeBody;
use edgezero_core::http::response_builder as edge_response_builder;
use edgezero_core::key_value_store::NoopKvStore;
use error_stack::Report;
use fastly::http::request::PendingRequest;
use fastly::http::{header, Method, StatusCode};
use fastly::Request;
use serde_json::json;
Expand Down Expand Up @@ -313,24 +312,25 @@ impl PlatformGeo for NoopGeo {

struct DisabledRouteProvider;

#[async_trait::async_trait(?Send)]
impl AuctionProvider for DisabledRouteProvider {
fn provider_name(&self) -> &'static str {
"disabled-route"
}

fn request_bids(
async fn request_bids(
&self,
_request: &AuctionRequest,
_context: &AuctionContext<'_>,
) -> Result<PendingRequest, Report<TrustedServerError>> {
) -> Result<PlatformPendingRequest, Report<TrustedServerError>> {
Err(Report::new(TrustedServerError::Auction {
message: "disabled route provider should not launch requests".to_string(),
}))
}

fn parse_response(
async fn parse_response(
&self,
_response: fastly::Response,
_response: PlatformResponse,
_response_time_ms: u64,
) -> Result<AuctionResponse, Report<TrustedServerError>> {
Err(Report::new(TrustedServerError::Auction {
Expand Down
24 changes: 17 additions & 7 deletions crates/trusted-server-core/src/auction/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ The auction orchestration system allows you to:
┌─────────────────────────────────────────────────────────┐
│ AuctionProvider Trait │
│ - request_bids() │
│ - request_bids() async │
│ - parse_response() │
│ - provider_name() │
│ - timeout_ms() │
│ - is_enabled() │
Expand Down Expand Up @@ -479,6 +480,7 @@ timeout_ms = 500
use async_trait::async_trait;
use crate::auction::provider::AuctionProvider;
use crate::auction::types::{AuctionContext, AuctionRequest, AuctionResponse};
use crate::platform::{PlatformPendingRequest, PlatformResponse};

pub struct YourAuctionProvider {
config: YourConfig,
Expand All @@ -494,11 +496,19 @@ impl AuctionProvider for YourAuctionProvider {
&self,
request: &AuctionRequest,
_context: &AuctionContext<'_>,
) -> Result<AuctionResponse, Report<TrustedServerError>> {
) -> Result<PlatformPendingRequest, Report<TrustedServerError>> {
// 1. Transform AuctionRequest to your provider's format
// 2. Make HTTP request to your provider
// 3. Parse response
// 4. Return AuctionResponse with bids
// 2. Launch HTTP request through services.http_client().send_async(...)
// 3. Return PlatformPendingRequest for the orchestrator to await
todo!()
}

async fn parse_response(
&self,
response: PlatformResponse,
Comment thread
prk-Jr marked this conversation as resolved.
response_time_ms: u64,
) -> Result<AuctionResponse, Report<TrustedServerError>> {
// 4. Parse PlatformResponse into AuctionResponse
todo!()
}

Expand Down Expand Up @@ -534,7 +544,7 @@ let orchestrator = AuctionOrchestrator::new(config);
orchestrator.register_provider(Arc::new(PrebidAuctionProvider::try_new(prebid_config)?));
orchestrator.register_provider(Arc::new(ApsAuctionProvider::new(aps_config)));

let result = orchestrator.run_auction(&request, &context).await?;
let result = orchestrator.run_auction(&request, &context, &services).await?;

// Check results
assert_eq!(result.winning_bids.len(), 2);
Expand All @@ -543,7 +553,7 @@ assert!(result.total_time_ms < 2000);

## Performance Considerations

- **Parallel Execution**: Currently runs sequentially in Fastly Compute (no tokio runtime), but structured for easy parallelization
- **Parallel Execution**: Providers are launched concurrently via `select()` over `PendingRequest`s; responses are processed as they become ready within the auction deadline
- **Timeouts**: Each provider has independent timeout; global timeout enforced at flow level
- **Error Handling**: Provider failures don't fail entire auction; partial results returned

Expand Down
7 changes: 1 addition & 6 deletions crates/trusted-server-core/src/auction/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use error_stack::{Report, ResultExt};
use http::{header, Request, Response, StatusCode};
use serde_json::Value as JsonValue;

use crate::compat;

use crate::auction::formats::AdRequest;
use crate::consent::gate_eids_by_consent;
use crate::constants::COOKIE_TS_EIDS;
Expand Down Expand Up @@ -157,13 +155,10 @@ pub async fn handle_auction(
log::warn!("Auction EIDs stripped by TCF consent gating");
}

// Provider context only needs request metadata.
let fastly_req = compat::to_fastly_request_ref(&http_req);

// Create auction context
let context = AuctionContext {
settings,
request: &fastly_req,
request: &http_req,
timeout_ms: settings.auction.timeout_ms,
provider_responses: None,
services,
Expand Down
2 changes: 1 addition & 1 deletion crates/trusted-server-core/src/auction/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub fn convert_tsjs_to_auction_request(
.get(header::USER_AGENT)
.and_then(|value| value.to_str().ok())
.map(str::to_string),
ip: services.client_info.client_ip.map(|ip| ip.to_string()),
ip: services.client_info().client_ip.map(|ip| ip.to_string()),
geo,
});

Expand Down
Loading
Loading