@antprofuse/saddle-skill 0.2.0 → 0.3.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,858 +0,0 @@
1
- //! Registry-only consumer template: generator-owned private artifact.
2
-
3
- use core::future::Future;
4
-
5
- use saddle::internal::{
6
- GeneratedApplicationBootstrap, GeneratedBootstrapError, GeneratedBootstrapToken,
7
- GeneratedCompiledAdapter, GeneratedContextFactory, GeneratedHttp1StaticFacts,
8
- generated_bootstrap_type_identity, generated_http1_framing_identity,
9
- };
10
- use saddle::{
11
- ApprovedExternalBundle, GeneratedApplicationConsumer, GeneratedApplicationOwner,
12
- GeneratedApplicationSeal, ProductionLauncher,
13
- };
14
- use saddle_admission::{
15
- ManagedBytes, ManagedResponse, ManagedResponseBuilder, ServiceCapacitySourceLeaf,
16
- };
17
- use saddle_db::Database;
18
- use saddle_db::internal::{
19
- DbBool, DbPair, DbU64, ManagedQueryParameters, ManagedQueryRow, QueryOptionalCreditDemand,
20
- QueryOptionalExecutionError, QueryOptionalOperationProof, StaticQueryOptionalOperation,
21
- StaticWriteOperation, TransactionDecision, TransactionExecutionError,
22
- TransactionOperationProof, WriteCreditDemand, WriteExecutionError, WriteOperationProof,
23
- write_transaction_finalization_proof,
24
- };
25
- use saddle_service::internal::{
26
- CompiledDbPermit, CompiledExecutionBuilder, CompiledRouteExecutionProof,
27
- CompiledServiceRegistry, CompiledServiceRegistryBuilder, EntryCapabilityLimits, EntryFraming,
28
- ExecutionError, ExecutionLayoutProof, FixedManagedCodec, GeneratedServiceCapacityArtifactOwner,
29
- InternalCallCapability, ManagedBool, ManagedCodec, ManagedPair, ManagedU64, ManagedValue,
30
- };
31
- use saddle_service::{Service, ServiceDescriptor};
32
-
33
- const BODY_BYTES: usize = 32;
34
- const OUTPUT_BYTES: usize = 64;
35
- const SERVICE_COUNT: usize = 6;
36
- const ROUTE_BYTES: usize = 128;
37
- const LOOKUP_USER_ORDINAL: usize = 0;
38
- const CREATE_ORDER_ORDINAL: usize = 1;
39
- const HEALTH_ORDINAL: usize = 2;
40
- const LINK_USER_ORDINAL: usize = 3;
41
- const TRANSFER_COMMIT_ORDINAL: usize = 4;
42
- const TRANSFER_ROLLBACK_ORDINAL: usize = 5;
43
- const OWNER_GENERATION: u64 = 1;
44
- const BUILD_IDENTITY: [u8; 32] = [0xb2; 32];
45
- const ARTIFACT_IDENTITY: [u8; 32] = [0xa2; 32];
46
-
47
- struct LookupUser;
48
-
49
- impl Service for LookupUser {
50
- type Request = ManagedU64;
51
- type Response = ManagedPair<ManagedU64, ManagedBool>;
52
- }
53
-
54
- struct CreateOrder;
55
-
56
- impl Service for CreateOrder {
57
- type Request = ManagedPair<ManagedU64, ManagedU64>;
58
- type Response = ManagedPair<ManagedU64, ManagedU64>;
59
- }
60
-
61
- struct Health;
62
-
63
- impl Service for Health {
64
- type Request = ManagedU64;
65
- type Response = ManagedU64;
66
- }
67
-
68
- struct LinkUserToOrderRoute;
69
- struct TransferOrderOwnerCommitRoute;
70
- struct TransferOrderOwnerRollbackRoute;
71
-
72
- type MutationRequest = ManagedPair<ManagedU64, ManagedU64>;
73
- type MutationResponse = ManagedPair<ManagedU64, ManagedU64>;
74
-
75
- impl Service for LinkUserToOrderRoute {
76
- type Request = MutationRequest;
77
- type Response = MutationResponse;
78
- }
79
-
80
- impl Service for TransferOrderOwnerCommitRoute {
81
- type Request = MutationRequest;
82
- type Response = MutationResponse;
83
- }
84
-
85
- impl Service for TransferOrderOwnerRollbackRoute {
86
- type Request = MutationRequest;
87
- type Response = MutationResponse;
88
- }
89
-
90
- type UserCodec =
91
- FixedManagedCodec<<LookupUser as Service>::Request, <LookupUser as Service>::Response>;
92
- type OrderCodec =
93
- FixedManagedCodec<<CreateOrder as Service>::Request, <CreateOrder as Service>::Response>;
94
- type HealthCodec = FixedManagedCodec<<Health as Service>::Request, <Health as Service>::Response>;
95
- type MutationCodec = FixedManagedCodec<MutationRequest, MutationResponse>;
96
- type CreateOrderToLookupUser = InternalCallCapability<CreateOrder, LookupUser>;
97
-
98
- struct FindUserOptional;
99
-
100
- impl StaticQueryOptionalOperation for FindUserOptional {
101
- type Parameters = ManagedQueryParameters<DbU64>;
102
- type Row = ManagedQueryRow<DbPair<DbU64, DbBool>>;
103
-
104
- const OPERATION: &'static str = "users.find_optional";
105
- const SQL: &'static str = "SELECT id, active FROM users WHERE id = ?";
106
- }
107
-
108
- struct FindOrderOptional;
109
-
110
- impl StaticQueryOptionalOperation for FindOrderOptional {
111
- type Parameters = ManagedQueryParameters<DbU64>;
112
- type Row = ManagedQueryRow<DbPair<DbU64, DbU64>>;
113
-
114
- const OPERATION: &'static str = "orders.find_optional";
115
- const SQL: &'static str = "SELECT id, amount FROM orders WHERE id = ?";
116
- }
117
-
118
- struct LinkUserToOrder;
119
-
120
- impl StaticWriteOperation for LinkUserToOrder {
121
- type Parameters = ManagedQueryParameters<DbPair<DbU64, DbU64>>;
122
-
123
- const OPERATION: &'static str = "user.link_order";
124
- const SQL: &'static str = "UPDATE users SET order_id = ? WHERE id = ?";
125
- }
126
-
127
- struct TransferOrderOwner;
128
-
129
- impl StaticWriteOperation for TransferOrderOwner {
130
- type Parameters = ManagedQueryParameters<DbPair<DbU64, DbU64>>;
131
-
132
- const OPERATION: &'static str = "order.transfer_owner";
133
- const SQL: &'static str = "UPDATE orders SET user_id = ? WHERE id = ?";
134
- }
135
-
136
- async fn lookup_user(
137
- request: <LookupUser as Service>::Request,
138
- ) -> Result<<LookupUser as Service>::Response, ExecutionError> {
139
- core::future::ready(()).await;
140
- Ok(ManagedPair(request, ManagedBool(true)))
141
- }
142
-
143
- async fn create_order(
144
- request: <CreateOrder as Service>::Request,
145
- ) -> Result<<CreateOrder as Service>::Response, ExecutionError> {
146
- core::future::ready(()).await;
147
- Ok(request)
148
- }
149
-
150
- async fn health(
151
- request: <Health as Service>::Request,
152
- ) -> Result<<Health as Service>::Response, ExecutionError> {
153
- core::future::ready(()).await;
154
- Ok(request)
155
- }
156
-
157
- async fn mutate(request: MutationRequest) -> Result<MutationResponse, ExecutionError> {
158
- core::future::ready(()).await;
159
- Ok(request)
160
- }
161
-
162
- fn bind_handler_layout<S, Request, Response, Codec, Handler, HandlerFuture>(
163
- handler: Handler,
164
- ) -> Result<ExecutionLayoutProof, ExecutionError>
165
- where
166
- S: Service<Request = Request, Response = Response>,
167
- Request: ManagedValue,
168
- Response: ManagedValue,
169
- Codec: ManagedCodec<Request, Response>,
170
- Handler: FnOnce(Request) -> HandlerFuture,
171
- HandlerFuture: Future<Output = Result<Response, ExecutionError>> + Send + 'static,
172
- {
173
- let _ = handler;
174
- ExecutionLayoutProof::bind::<S, BODY_BYTES, OUTPUT_BYTES, Request, Response, Codec, HandlerFuture>(
175
- )
176
- }
177
-
178
- fn handler_layout(ordinal: usize) -> Option<ExecutionLayoutProof> {
179
- match ordinal {
180
- LOOKUP_USER_ORDINAL => {
181
- bind_handler_layout::<LookupUser, _, _, UserCodec, _, _>(lookup_user).ok()
182
- }
183
- CREATE_ORDER_ORDINAL => {
184
- bind_handler_layout::<CreateOrder, _, _, OrderCodec, _, _>(create_order).ok()
185
- }
186
- HEALTH_ORDINAL => bind_handler_layout::<Health, _, _, HealthCodec, _, _>(health).ok(),
187
- LINK_USER_ORDINAL => {
188
- bind_handler_layout::<LinkUserToOrderRoute, _, _, MutationCodec, _, _>(mutate).ok()
189
- }
190
- TRANSFER_COMMIT_ORDINAL => {
191
- bind_handler_layout::<TransferOrderOwnerCommitRoute, _, _, MutationCodec, _, _>(mutate)
192
- .ok()
193
- }
194
- TRANSFER_ROLLBACK_ORDINAL => {
195
- bind_handler_layout::<TransferOrderOwnerRollbackRoute, _, _, MutationCodec, _, _>(
196
- mutate,
197
- )
198
- .ok()
199
- }
200
- _ => None,
201
- }
202
- }
203
-
204
- fn layout(ordinal: usize) -> Option<CompiledRouteExecutionProof> {
205
- match ordinal {
206
- LOOKUP_USER_ORDINAL => Some(
207
- handler_layout(ordinal)?
208
- .with_query_optional(QueryOptionalOperationProof::<FindUserOptional>::bind().ok()?),
209
- ),
210
- CREATE_ORDER_ORDINAL => {
211
- Some(handler_layout(ordinal)?.with_query_optional(
212
- QueryOptionalOperationProof::<FindOrderOptional>::bind().ok()?,
213
- ))
214
- }
215
- HEALTH_ORDINAL => Some(handler_layout(ordinal)?.without_db()),
216
- LINK_USER_ORDINAL => Some(
217
- handler_layout(ordinal)?
218
- .with_write(WriteOperationProof::<LinkUserToOrder>::bind().ok()?),
219
- ),
220
- TRANSFER_COMMIT_ORDINAL | TRANSFER_ROLLBACK_ORDINAL => Some(
221
- handler_layout(ordinal)?
222
- .with_transaction(TransactionOperationProof::<TransferOrderOwner>::bind().ok()?),
223
- ),
224
- _ => None,
225
- }
226
- }
227
-
228
- fn compiled_registry() -> CompiledServiceRegistry {
229
- let mut registry =
230
- CompiledServiceRegistryBuilder::new(SERVICE_COUNT).expect("bounded generated registry");
231
- registry
232
- .register::<LookupUser>(ServiceDescriptor::new("users", "user", "lookup"))
233
- .expect("generated user marker");
234
- registry
235
- .register::<CreateOrder>(ServiceDescriptor::new("orders", "order", "create"))
236
- .expect("generated order marker");
237
- registry
238
- .register::<Health>(ServiceDescriptor::new("system", "health", "check"))
239
- .expect("generated no-DB marker");
240
- registry
241
- .register::<LinkUserToOrderRoute>(ServiceDescriptor::new("users", "user", "link_order"))
242
- .expect("generated standalone write marker");
243
- registry
244
- .register::<TransferOrderOwnerCommitRoute>(ServiceDescriptor::new(
245
- "orders",
246
- "order",
247
- "transfer_owner_commit",
248
- ))
249
- .expect("generated transaction commit marker");
250
- registry
251
- .register::<TransferOrderOwnerRollbackRoute>(ServiceDescriptor::new(
252
- "orders",
253
- "order",
254
- "transfer_owner_rollback",
255
- ))
256
- .expect("generated transaction rollback marker");
257
- registry.freeze().expect("generated registry")
258
- }
259
-
260
- pub(crate) struct GeneratedRequestContext {
261
- database: Database,
262
- cancel: saddle_admission::RequestCancelFuture,
263
- shutdown: saddle_admission::RequestShutdownFuture,
264
- }
265
-
266
- pub(crate) struct GeneratedRequestContextFactory;
267
-
268
- impl GeneratedContextFactory<GeneratedRequestContext> for GeneratedRequestContextFactory {
269
- fn make_context(
270
- &self,
271
- memory: &saddle_admission::RequestMemory,
272
- database: Option<&Database>,
273
- ) -> GeneratedRequestContext {
274
- GeneratedRequestContext {
275
- database: database.expect("DB route has a managed database").clone(),
276
- cancel: memory
277
- .cancel_requested()
278
- .expect("accepted generated request owns its cancel signal"),
279
- shutdown: memory
280
- .shutdown_requested()
281
- .expect("accepted generated request owns its shutdown signal"),
282
- }
283
- }
284
- }
285
-
286
- fn decode_u64(body: &[u8]) -> Result<ManagedU64, ExecutionError> {
287
- let bytes: [u8; 8] = body
288
- .get(..8)
289
- .ok_or(ExecutionError::InvalidInput)?
290
- .try_into()
291
- .map_err(|_| ExecutionError::InvalidInput)?;
292
- Ok(ManagedU64(u64::from_le_bytes(bytes)))
293
- }
294
-
295
- fn encode_pair(
296
- output: &mut ManagedResponseBuilder,
297
- first: ManagedU64,
298
- second: ManagedU64,
299
- ) -> Result<(), ExecutionError> {
300
- output
301
- .try_extend_from_slice(&first.0.to_le_bytes())
302
- .map_err(|_| ExecutionError::OutputTooLarge)?;
303
- output
304
- .try_extend_from_slice(&second.0.to_le_bytes())
305
- .map_err(|_| ExecutionError::OutputTooLarge)
306
- }
307
-
308
- #[allow(clippy::manual_async_fn)]
309
- fn dispatch(
310
- ordinal: usize,
311
- context: GeneratedRequestContext,
312
- body: ManagedBytes,
313
- db: CompiledDbPermit,
314
- mut output: ManagedResponseBuilder,
315
- ) -> impl Future<Output = Result<ManagedResponse, ExecutionError>> + Send + 'static + use<> {
316
- let decoded = match ordinal {
317
- LOOKUP_USER_ORDINAL | HEALTH_ORDINAL => {
318
- decode_u64(body.as_slice()).map(|first| (first, None))
319
- }
320
- CREATE_ORDER_ORDINAL
321
- | LINK_USER_ORDINAL
322
- | TRANSFER_COMMIT_ORDINAL
323
- | TRANSFER_ROLLBACK_ORDINAL => decode_u64(body.as_slice()).and_then(|first| {
324
- decode_u64(
325
- body.as_slice()
326
- .get(8..)
327
- .ok_or(ExecutionError::InvalidInput)?,
328
- )
329
- .map(|second| (first, Some(second)))
330
- }),
331
- _ => Err(ExecutionError::UnknownExecution),
332
- };
333
- drop(body);
334
-
335
- async move {
336
- let GeneratedRequestContext {
337
- database,
338
- cancel,
339
- shutdown,
340
- } = context;
341
- let (first, second) = decoded?;
342
- match (ordinal, second) {
343
- (LOOKUP_USER_ORDINAL, None) => {
344
- let invocation = QueryOptionalOperationProof::<FindUserOptional>::bind()
345
- .map_err(|_| ExecutionError::Business)?
346
- .invocation(ManagedQueryParameters(DbU64(first.0)));
347
- let execution = db.handoff_query_optional(invocation)?;
348
- let row = database
349
- .execute_query_optional(execution, cancel, shutdown)
350
- .await
351
- .map_err(map_query_error)?
352
- .into_option()
353
- .ok_or(ExecutionError::Business)?;
354
- let ManagedQueryRow(DbPair(id, active)) = row;
355
- let response = lookup_user(ManagedU64(id.0)).await?;
356
- encode_pair(&mut output, response.0, ManagedU64(u64::from(active.0)))?;
357
- }
358
- (CREATE_ORDER_ORDINAL, Some(_second)) => {
359
- let invocation = QueryOptionalOperationProof::<FindOrderOptional>::bind()
360
- .map_err(|_| ExecutionError::Business)?
361
- .invocation(ManagedQueryParameters(DbU64(first.0)));
362
- let execution = db.handoff_query_optional(invocation)?;
363
- let row = database
364
- .execute_query_optional(execution, cancel, shutdown)
365
- .await
366
- .map_err(map_query_error)?
367
- .into_option()
368
- .ok_or(ExecutionError::Business)?;
369
- let ManagedQueryRow(DbPair(id, amount)) = row;
370
- let response =
371
- create_order(ManagedPair(ManagedU64(id.0), ManagedU64(amount.0))).await?;
372
- encode_pair(&mut output, response.0, response.1)?;
373
- }
374
- (HEALTH_ORDINAL, None) => {
375
- if !db.is_none() {
376
- return Err(ExecutionError::InvalidInput);
377
- }
378
- let response = health(first).await?;
379
- encode_pair(&mut output, response, ManagedU64(0))?;
380
- }
381
- (LINK_USER_ORDINAL, Some(second)) => {
382
- let parameters = ManagedQueryParameters(DbPair(DbU64(first.0), DbU64(second.0)));
383
- let invocation = WriteOperationProof::<LinkUserToOrder>::bind()
384
- .map_err(|_| ExecutionError::Business)?
385
- .invocation(parameters);
386
- let execution = db.handoff_write(invocation)?;
387
- let result = database
388
- .execute_write(execution, cancel, shutdown)
389
- .await
390
- .map_err(map_write_error)?;
391
- encode_pair(
392
- &mut output,
393
- ManagedU64(result.rows_affected()),
394
- ManagedU64(result.last_insert_id()),
395
- )?;
396
- }
397
- (TRANSFER_COMMIT_ORDINAL | TRANSFER_ROLLBACK_ORDINAL, Some(second)) => {
398
- let decision = if ordinal == TRANSFER_COMMIT_ORDINAL {
399
- TransactionDecision::Commit
400
- } else {
401
- TransactionDecision::Rollback
402
- };
403
- let parameters = ManagedQueryParameters(DbPair(DbU64(first.0), DbU64(second.0)));
404
- let invocation = TransactionOperationProof::<TransferOrderOwner>::bind()
405
- .map_err(|_| ExecutionError::Business)?
406
- .invocation(parameters, decision);
407
- let execution = db.handoff_transaction(invocation)?;
408
- let result = database
409
- .execute_transaction(execution, cancel, shutdown)
410
- .await
411
- .map_err(map_transaction_error)?;
412
- encode_pair(
413
- &mut output,
414
- ManagedU64(result.rows_affected()),
415
- ManagedU64(result.last_insert_id()),
416
- )?;
417
- }
418
- _ => return Err(ExecutionError::InvalidInput),
419
- }
420
- output
421
- .finish()
422
- .map_err(|_| ExecutionError::ResponseReservationFailed)
423
- }
424
- }
425
-
426
- fn map_query_error(error: QueryOptionalExecutionError) -> ExecutionError {
427
- match error {
428
- QueryOptionalExecutionError::ConnectionUnavailable
429
- | QueryOptionalExecutionError::QueryFailed
430
- | QueryOptionalExecutionError::InvalidRow
431
- | QueryOptionalExecutionError::FinalizerFailed => ExecutionError::DependencyExecutionFailed,
432
- QueryOptionalExecutionError::Cancelled | QueryOptionalExecutionError::Shutdown => {
433
- ExecutionError::DependencyUnavailable
434
- }
435
- }
436
- }
437
-
438
- fn map_write_error(error: WriteExecutionError) -> ExecutionError {
439
- match error {
440
- WriteExecutionError::ConnectionUnavailable
441
- | WriteExecutionError::WriteFailed
442
- | WriteExecutionError::FinalizerFailed => ExecutionError::DependencyExecutionFailed,
443
- WriteExecutionError::Cancelled | WriteExecutionError::Shutdown => {
444
- ExecutionError::DependencyUnavailable
445
- }
446
- }
447
- }
448
-
449
- fn map_transaction_error(error: TransactionExecutionError) -> ExecutionError {
450
- match error {
451
- TransactionExecutionError::BusinessRollback => ExecutionError::Business,
452
- TransactionExecutionError::ConnectionUnavailable
453
- | TransactionExecutionError::BeginFailed
454
- | TransactionExecutionError::WriteFailed
455
- | TransactionExecutionError::CommitFailed
456
- | TransactionExecutionError::RollbackFailed
457
- | TransactionExecutionError::FinalizerFailed => ExecutionError::DependencyExecutionFailed,
458
- TransactionExecutionError::Cancelled | TransactionExecutionError::Shutdown => {
459
- ExecutionError::DependencyUnavailable
460
- }
461
- }
462
- }
463
-
464
- macro_rules! generated_builder {
465
- () => {{
466
- let mut builder = CompiledExecutionBuilder::<_, _, _, _, BODY_BYTES, OUTPUT_BYTES>::new(
467
- compiled_registry(),
468
- dispatch,
469
- layout,
470
- EntryCapabilityLimits::new(
471
- SERVICE_COUNT,
472
- ROUTE_BYTES,
473
- ROUTE_BYTES,
474
- SERVICE_COUNT,
475
- SERVICE_COUNT,
476
- ),
477
- )
478
- .expect("single generated assembly");
479
- builder
480
- .expose::<LookupUser>(
481
- b"/users/lookup",
482
- EntryFraming::post_managed_content_length(),
483
- )
484
- .expect("generated user route");
485
- builder
486
- .expose::<CreateOrder>(
487
- b"/orders/create",
488
- EntryFraming::post_managed_content_length(),
489
- )
490
- .expect("generated order route");
491
- builder
492
- .expose::<Health>(b"/health", EntryFraming::post_managed_content_length())
493
- .expect("generated no-DB route");
494
- builder
495
- .expose::<LinkUserToOrderRoute>(
496
- b"/users/link-order",
497
- EntryFraming::post_managed_content_length(),
498
- )
499
- .expect("generated standalone write route");
500
- builder
501
- .expose::<TransferOrderOwnerCommitRoute>(
502
- b"/orders/transfer-owner/commit",
503
- EntryFraming::post_managed_content_length(),
504
- )
505
- .expect("generated transaction commit route");
506
- builder
507
- .expose::<TransferOrderOwnerRollbackRoute>(
508
- b"/orders/transfer-owner/rollback",
509
- EntryFraming::post_managed_content_length(),
510
- )
511
- .expect("generated transaction rollback route");
512
- let edge: CreateOrderToLookupUser = builder
513
- .bind_internal_call::<CreateOrder, LookupUser>()
514
- .expect("generated typed call edge");
515
- (builder, edge)
516
- }};
517
- }
518
-
519
- fn verify_static_inputs() {
520
- let finalization = saddle_db::internal::query_optional_finalization_proof();
521
- assert_eq!(finalization.cancel_external_io_awaits(), 0);
522
- assert_eq!(finalization.shutdown_external_io_awaits(), 0);
523
- assert_eq!(finalization.panic_external_io_awaits(), 0);
524
- assert!(finalization.releases_pool_size_before_permit());
525
- assert!(finalization.normal_return_requires_termination_bound());
526
-
527
- let user_db = QueryOptionalOperationProof::<FindUserOptional>::bind()
528
- .expect("generated user DB operation");
529
- let user_db_layout = user_db.layout();
530
- let user_invocation = user_db.invocation(ManagedQueryParameters(DbU64(7)));
531
- assert_eq!(user_invocation.parameters().0, DbU64(7));
532
-
533
- let order_db = QueryOptionalOperationProof::<FindOrderOptional>::bind()
534
- .expect("generated order DB operation");
535
- let order_db_layout = order_db.layout();
536
- let order_invocation = order_db.invocation(ManagedQueryParameters(DbU64(11)));
537
- assert_eq!(order_invocation.parameters().0, DbU64(11));
538
-
539
- let user_route_db = user_db_layout.credits();
540
- let order_route_db = order_db_layout
541
- .credits()
542
- .merge_route_max(user_db_layout.credits());
543
- assert_route_credit(user_route_db);
544
- assert_route_credit(order_route_db);
545
-
546
- let write = WriteOperationProof::<LinkUserToOrder>::bind()
547
- .expect("generated standalone write proof")
548
- .layout();
549
- let transaction = TransactionOperationProof::<TransferOrderOwner>::bind()
550
- .expect("generated transaction proof")
551
- .layout();
552
- assert_eq!(write.parameter_bytes(), 16);
553
- assert_eq!(transaction.parameter_bytes(), 16);
554
- assert_write_route_credit(write.credits());
555
- assert_write_route_credit(transaction.credits());
556
-
557
- let write_finalization = write_transaction_finalization_proof();
558
- assert_eq!(write_finalization.cancel_external_io_awaits(), 0);
559
- assert_eq!(write_finalization.shutdown_external_io_awaits(), 0);
560
- assert_eq!(write_finalization.panic_external_io_awaits(), 0);
561
- assert!(write_finalization.single_connection());
562
- assert!(!write_finalization.nested_transactions());
563
- assert!(write_finalization.releases_pool_size_before_permit());
564
- assert!(write_finalization.normal_return_requires_termination_bound());
565
- }
566
-
567
- struct GeneratedArtifactIdentity;
568
-
569
- impl GeneratedServiceCapacityArtifactOwner for GeneratedArtifactIdentity {
570
- fn build_identity(&self) -> [u8; 32] {
571
- BUILD_IDENTITY
572
- }
573
- fn artifact_identity(&self) -> [u8; 32] {
574
- ARTIFACT_IDENTITY
575
- }
576
- fn owner_generation(&self) -> u64 {
577
- OWNER_GENERATION
578
- }
579
- }
580
-
581
- fn generated_bootstrap<A>(
582
- token: GeneratedBootstrapToken,
583
- capability: A,
584
- common: [[u8; 32]; 3],
585
- ) -> Result<
586
- (
587
- GeneratedApplicationBootstrap<A, GeneratedRequestContextFactory, SERVICE_COUNT>,
588
- [u8; 32],
589
- ),
590
- GeneratedBootstrapError,
591
- >
592
- where
593
- A: GeneratedCompiledAdapter<Context = GeneratedRequestContext>,
594
- {
595
- let user_route = token.bind_route(b"/users/lookup", 8)?;
596
- let order_route = token.bind_route(b"/orders/create", 16)?;
597
- let health_route = token.bind_route(b"/health", 8)?;
598
- let write_route = token.bind_route(b"/users/link-order", 16)?;
599
- let commit_route = token.bind_route(b"/orders/transfer-owner/commit", 16)?;
600
- let rollback_route = token.bind_route(b"/orders/transfer-owner/rollback", 16)?;
601
- let bootstrap_type =
602
- generated_bootstrap_type_identity::<A, GeneratedRequestContextFactory, SERVICE_COUNT>();
603
- let profile = token.approve_http1_facts(GeneratedHttp1StaticFacts {
604
- route_count: SERVICE_COUNT,
605
- route_set_identity: common[2],
606
- framing_identity: generated_http1_framing_identity(),
607
- static_layout_identity: bootstrap_type,
608
- db_finalization_proof: saddle_db::internal::query_optional_finalization_proof(),
609
- })?;
610
- let bootstrap = token.consume(
611
- capability,
612
- GeneratedRequestContextFactory,
613
- [
614
- user_route,
615
- order_route,
616
- health_route,
617
- write_route,
618
- commit_route,
619
- rollback_route,
620
- ],
621
- profile,
622
- )?;
623
- Ok((bootstrap, bootstrap_type))
624
- }
625
-
626
- pub(crate) struct GeneratedOwner;
627
-
628
- impl GeneratedApplicationOwner for GeneratedOwner {
629
- fn consume<K>(self, seal: GeneratedApplicationSeal, consumer: K) -> saddle::Result<()>
630
- where
631
- K: GeneratedApplicationConsumer,
632
- {
633
- verify_static_inputs();
634
- let (builder, _edge) = generated_builder!();
635
- let bundle = builder
636
- .freeze_with_capacity_leaf(GeneratedArtifactIdentity)
637
- .expect("single generated freeze and capacity bundle");
638
- let common = bundle.capacity_source().common_identities();
639
- let (bootstrap, _bootstrap_type) =
640
- generated_bootstrap(seal.preflight_token(), bundle, common)
641
- .map_err(|_| generated_error("skill.generated_preflight"))?;
642
- let parts = seal
643
- .bind(bootstrap)
644
- .map_err(|_| generated_error("skill.generated_binding"))?;
645
- consumer.consume(parts)
646
- }
647
- }
648
-
649
- fn generated_error(code: &'static str) -> saddle::SaddleError {
650
- saddle::SaddleError::new(
651
- saddle::ErrorKind::Infrastructure,
652
- code,
653
- "generated owner rejected",
654
- )
655
- }
656
-
657
- impl crate::GeneratedProbe {
658
- #[allow(dead_code)]
659
- pub fn run<B>(bundle: B, config: saddle::SaddleConfig) -> saddle::Result<()>
660
- where
661
- B: ApprovedExternalBundle,
662
- {
663
- ProductionLauncher::verify(bundle)?.run(config, GeneratedOwner)
664
- }
665
- }
666
-
667
- pub(crate) fn verify_startup() {
668
- verify_static_inputs();
669
- fn require_owner<T: GeneratedApplicationOwner>() {}
670
- require_owner::<GeneratedOwner>();
671
- }
672
-
673
- pub(crate) struct MachineValues {
674
- pub(crate) dispatcher_future: usize,
675
- pub(crate) user_handler_future: usize,
676
- pub(crate) order_handler_future: usize,
677
- pub(crate) health_handler_future: usize,
678
- pub(crate) user_commitment: usize,
679
- pub(crate) order_commitment: usize,
680
- pub(crate) health_commitment: usize,
681
- pub(crate) user_db_parameter: usize,
682
- pub(crate) user_db_optional_row: usize,
683
- pub(crate) order_db_parameter: usize,
684
- pub(crate) order_db_optional_row: usize,
685
- pub(crate) user_route_connections: u32,
686
- pub(crate) user_route_operations: u32,
687
- pub(crate) order_route_connections: u32,
688
- pub(crate) order_route_operations: u32,
689
- pub(crate) health_route_connections: u32,
690
- pub(crate) health_route_operations: u32,
691
- }
692
-
693
- fn assert_route_credit(credit: QueryOptionalCreditDemand) {
694
- assert_eq!(credit.connections(), 1);
695
- assert_eq!(credit.operations(), 1);
696
- }
697
-
698
- fn assert_write_route_credit(credit: WriteCreditDemand) {
699
- assert_eq!(credit.connections(), 1);
700
- assert_eq!(credit.operations(), 1);
701
- }
702
-
703
- fn dispatcher_future_bytes<Factory, DispatcherFuture>(factory: Factory) -> usize
704
- where
705
- Factory: Fn(
706
- usize,
707
- GeneratedRequestContext,
708
- ManagedBytes,
709
- CompiledDbPermit,
710
- ManagedResponseBuilder,
711
- ) -> DispatcherFuture,
712
- DispatcherFuture: Future<Output = Result<ManagedResponse, ExecutionError>> + Send + 'static,
713
- {
714
- let _ = factory;
715
- core::mem::size_of::<DispatcherFuture>()
716
- }
717
-
718
- pub(crate) fn machine_values() -> MachineValues {
719
- let user = handler_layout(LOOKUP_USER_ORDINAL).expect("generated user layout");
720
- let order = handler_layout(CREATE_ORDER_ORDINAL).expect("generated order layout");
721
- let health = handler_layout(HEALTH_ORDINAL).expect("generated health layout");
722
- let user_db = QueryOptionalOperationProof::<FindUserOptional>::bind()
723
- .expect("generated user DB operation")
724
- .layout();
725
- let order_db = QueryOptionalOperationProof::<FindOrderOptional>::bind()
726
- .expect("generated order DB operation")
727
- .layout();
728
- let user_route_db = user_db.credits();
729
- let order_route_db = order_db.credits().merge_route_max(user_db.credits());
730
- MachineValues {
731
- dispatcher_future: dispatcher_future_bytes(dispatch),
732
- user_handler_future: user.future_bytes(),
733
- order_handler_future: order.future_bytes(),
734
- health_handler_future: health.future_bytes(),
735
- user_commitment: user.commitment().expect("generated user commitment"),
736
- order_commitment: order.commitment().expect("generated order commitment"),
737
- health_commitment: health.commitment().expect("generated health commitment"),
738
- user_db_parameter: user_db.parameter_bytes(),
739
- user_db_optional_row: user_db.optional_row_bytes(),
740
- order_db_parameter: order_db.parameter_bytes(),
741
- order_db_optional_row: order_db.optional_row_bytes(),
742
- user_route_connections: user_route_db.connections(),
743
- user_route_operations: user_route_db.operations(),
744
- order_route_connections: order_route_db.connections(),
745
- order_route_operations: order_route_db.operations(),
746
- health_route_connections: 0,
747
- health_route_operations: 0,
748
- }
749
- }
750
-
751
- #[cfg(test)]
752
- mod tests {
753
- use super::*;
754
-
755
- fn swapped_layout(ordinal: usize) -> Option<CompiledRouteExecutionProof> {
756
- match ordinal {
757
- LOOKUP_USER_ORDINAL => layout(CREATE_ORDER_ORDINAL),
758
- CREATE_ORDER_ORDINAL => layout(LOOKUP_USER_ORDINAL),
759
- _ => None,
760
- }
761
- }
762
-
763
- #[test]
764
- fn generated_bootstrap_factory_typechecks() {
765
- verify_startup();
766
- }
767
-
768
- #[test]
769
- fn generated_health_route_has_no_db_resources() {
770
- let (builder, _edge) = generated_builder!();
771
- let capability = builder.freeze().expect("single generated freeze");
772
- let health = capability
773
- .lookup(
774
- b"/health",
775
- EntryFraming::post_managed_content_length(),
776
- Some(8),
777
- )
778
- .expect("generated no-DB lookup");
779
- assert!(health.db_demand().is_none());
780
- assert_eq!(health.db_demand().connections(), 0);
781
- assert_eq!(health.db_demand().operations(), 0);
782
- }
783
-
784
- #[test]
785
- fn generated_write_and_transaction_routes_share_the_only_capability() {
786
- let (builder, _edge) = generated_builder!();
787
- let capability = builder.freeze().expect("single unified generated freeze");
788
- for route in [
789
- b"/users/link-order".as_slice(),
790
- b"/orders/transfer-owner/commit".as_slice(),
791
- b"/orders/transfer-owner/rollback".as_slice(),
792
- ] {
793
- let lookup = capability
794
- .lookup(route, EntryFraming::post_managed_content_length(), Some(16))
795
- .expect("generated unified C1 route lookup");
796
- assert_eq!(lookup.db_demand().connections(), 1);
797
- assert_eq!(lookup.db_demand().operations(), 1);
798
- }
799
- }
800
-
801
- #[test]
802
- fn swapped_layout_is_rejected() {
803
- let mut builder = CompiledExecutionBuilder::<_, _, _, _, BODY_BYTES, OUTPUT_BYTES>::new(
804
- compiled_registry(),
805
- dispatch,
806
- swapped_layout,
807
- EntryCapabilityLimits::new(
808
- SERVICE_COUNT,
809
- ROUTE_BYTES,
810
- ROUTE_BYTES,
811
- SERVICE_COUNT,
812
- SERVICE_COUNT,
813
- ),
814
- )
815
- .expect("candidate assembly");
816
- assert!(
817
- builder
818
- .expose::<LookupUser>(
819
- b"/users/lookup",
820
- EntryFraming::post_managed_content_length(),
821
- )
822
- .is_err()
823
- );
824
- }
825
-
826
- #[test]
827
- fn swapped_registry_ordinal_is_rejected() {
828
- let mut registry =
829
- CompiledServiceRegistryBuilder::new(SERVICE_COUNT).expect("bounded registry");
830
- registry
831
- .register::<CreateOrder>(ServiceDescriptor::new("orders", "order", "create"))
832
- .expect("swapped order marker");
833
- registry
834
- .register::<LookupUser>(ServiceDescriptor::new("users", "user", "lookup"))
835
- .expect("swapped user marker");
836
- let mut builder = CompiledExecutionBuilder::<_, _, _, _, BODY_BYTES, OUTPUT_BYTES>::new(
837
- registry.freeze().expect("swapped registry"),
838
- dispatch,
839
- layout,
840
- EntryCapabilityLimits::new(
841
- SERVICE_COUNT,
842
- ROUTE_BYTES,
843
- ROUTE_BYTES,
844
- SERVICE_COUNT,
845
- SERVICE_COUNT,
846
- ),
847
- )
848
- .expect("candidate assembly");
849
- assert!(
850
- builder
851
- .expose::<LookupUser>(
852
- b"/users/lookup",
853
- EntryFraming::post_managed_content_length(),
854
- )
855
- .is_err()
856
- );
857
- }
858
- }