ApiExecutor

Struct ApiExecutor 

Source
pub struct ApiExecutor<C> { /* private fields */ }
Expand description

A stateful executor for API operations that maintains context across multiple calls.

ImplementationsΒ§

SourceΒ§

impl<C> ApiExecutor<C>

Source

pub fn new(context: C) -> Self

Creates a new ApiExecutor that owns the provided context.

Examples found in repository?
examples/executor_pattern.rs (line 218)
213fn main() {
214    println!("πŸ”§ ApiThing Executor Pattern Example");
215    println!("====================================\n");
216
217    // Create an executor that manages the context for us
218    let mut executor = ApiExecutor::new(AppContext::new("production_db".to_string()));
219
220    println!("πŸ—οΈ  Created ApiExecutor with context");
221    println!("πŸ“Š Connection: {}", executor.context().connection_pool());
222    println!(
223        "πŸ”’ Initial transaction count: {}\n",
224        executor.context().transaction_count()
225    );
226
227    // === User Operations ===
228    println!("πŸ‘₯ USER OPERATIONS");
229    println!("==================");
230
231    // Create multiple users using the executor
232    let users = vec![
233        ("Alice Johnson", "alice@company.com"),
234        ("Bob Smith", "bob@company.com"),
235        ("Carol Davis", "carol@company.com"),
236    ];
237
238    let mut created_users = Vec::new();
239    for (name, email) in users {
240        match executor.execute(
241            CreateUser,
242            &CreateUserProps {
243                name: name.to_string(),
244                email: email.to_string(),
245            },
246        ) {
247            Ok(user) => {
248                println!("βœ… Created user: {} (ID: {})", user.name, user.id);
249                created_users.push(user);
250            }
251            Err(e) => {
252                println!("❌ Failed to create user {}: {:?}", name, e);
253                return;
254            }
255        }
256    }
257
258    println!(
259        "πŸ”’ Transaction count after user creation: {}\n",
260        executor.context().transaction_count()
261    );
262
263    // === Product Operations (Same Context) ===
264    println!("πŸ“¦ PRODUCT OPERATIONS");
265    println!("====================");
266
267    // Create products using the same executor/context
268    let products = vec![
269        ("Laptop Pro", 1299.99, "Electronics"),
270        ("Office Chair", 249.50, "Furniture"),
271        ("Coffee Mug", 12.99, "Kitchen"),
272    ];
273
274    let mut created_products = Vec::new();
275    for (name, price, category) in products {
276        match executor.execute(
277            CreateProduct,
278            &CreateProductProps {
279                name: name.to_string(),
280                price,
281                category: category.to_string(),
282            },
283        ) {
284            Ok(product) => {
285                println!(
286                    "βœ… Created product: {} (ID: {}, Price: ${:.2})",
287                    product.name, product.id, product.price
288                );
289                created_products.push(product);
290            }
291            Err(e) => {
292                println!("❌ Failed to create product {}: {:?}", name, e);
293                return;
294            }
295        }
296    }
297
298    println!(
299        "πŸ”’ Transaction count after product creation: {}\n",
300        executor.context().transaction_count()
301    );
302
303    // === Cross-Family Operations ===
304    println!("πŸ”„ CROSS-FAMILY LOOKUPS");
305    println!("=======================");
306
307    // Find users and products using the same context
308    // This demonstrates how the cache works across different API families
309
310    println!("πŸ” Looking up created entities...");
311
312    // Find first user
313    if let Some(user) = created_users.first() {
314        match executor.execute(FindUser, &FindUserProps { user_id: user.id }) {
315            Ok(found_user) => println!("πŸ‘€ Found user: {} ({})", found_user.name, found_user.email),
316            Err(e) => println!("❌ Failed to find user: {:?}", e),
317        }
318    }
319
320    // Find first product
321    if let Some(product) = created_products.first() {
322        match executor.execute(
323            FindProduct,
324            &FindProductProps {
325                product_id: product.id,
326            },
327        ) {
328            Ok(found_product) => println!(
329                "πŸ“¦ Found product: {} (${:.2})",
330                found_product.name, found_product.price
331            ),
332            Err(e) => println!("❌ Failed to find product: {:?}", e),
333        }
334    }
335
336    // === Context Inspection ===
337    println!("\nπŸ“Š CONTEXT INSPECTION");
338    println!("=====================");
339
340    let context = executor.context();
341    println!(
342        "πŸ”’ Final transaction count: {}",
343        context.transaction_count()
344    );
345    println!("πŸ’Ύ Cache entries: {} items", context.cache().len());
346
347    // Show cache contents
348    println!("πŸ“‹ Cached items:");
349    for (key, value) in context.cache().iter() {
350        // Truncate long values for display
351        let display_value = if value.len() > 50 {
352            format!("{}...", &value[..47])
353        } else {
354            value.clone()
355        };
356        println!("   β€’ {}: {}", key, display_value);
357    }
358
359    // === Executor Benefits Demo ===
360    println!("\nπŸ’‘ EXECUTOR BENEFITS");
361    println!("====================");
362
363    // Show how we can access the context for debugging or inspection
364    let final_context = executor.context();
365    println!("βœ… Centralized state management:");
366    println!(
367        "   β€’ {} total operations executed",
368        final_context.transaction_count()
369    );
370    println!("   β€’ {} entities cached", final_context.cache().len());
371    println!("   β€’ Single context shared across {} API families", 2);
372
373    println!("\nπŸŽ‰ Executor pattern example completed successfully!");
374    println!("πŸ’‘ Key advantages of ApiExecutor:");
375    println!("   β€’ Ergonomic API: executor.execute(Operation, &parameters)");
376    println!("   β€’ Centralized context management with owned context");
377    println!("   β€’ Consistent patterns across different API families");
378    println!("   β€’ Easy context inspection and debugging");
379    println!("   β€’ Efficient state sharing (cache, connections, etc.)");
380}
Source

pub fn execute<P, Op>( &mut self, _op: Op, parameters: &P, ) -> Result<Op::Output, Op::Error>
where Op: ApiOperation<C, P>,

Executes an API operation using this executor’s context.

Examples found in repository?
examples/executor_pattern.rs (lines 240-246)
213fn main() {
214    println!("πŸ”§ ApiThing Executor Pattern Example");
215    println!("====================================\n");
216
217    // Create an executor that manages the context for us
218    let mut executor = ApiExecutor::new(AppContext::new("production_db".to_string()));
219
220    println!("πŸ—οΈ  Created ApiExecutor with context");
221    println!("πŸ“Š Connection: {}", executor.context().connection_pool());
222    println!(
223        "πŸ”’ Initial transaction count: {}\n",
224        executor.context().transaction_count()
225    );
226
227    // === User Operations ===
228    println!("πŸ‘₯ USER OPERATIONS");
229    println!("==================");
230
231    // Create multiple users using the executor
232    let users = vec![
233        ("Alice Johnson", "alice@company.com"),
234        ("Bob Smith", "bob@company.com"),
235        ("Carol Davis", "carol@company.com"),
236    ];
237
238    let mut created_users = Vec::new();
239    for (name, email) in users {
240        match executor.execute(
241            CreateUser,
242            &CreateUserProps {
243                name: name.to_string(),
244                email: email.to_string(),
245            },
246        ) {
247            Ok(user) => {
248                println!("βœ… Created user: {} (ID: {})", user.name, user.id);
249                created_users.push(user);
250            }
251            Err(e) => {
252                println!("❌ Failed to create user {}: {:?}", name, e);
253                return;
254            }
255        }
256    }
257
258    println!(
259        "πŸ”’ Transaction count after user creation: {}\n",
260        executor.context().transaction_count()
261    );
262
263    // === Product Operations (Same Context) ===
264    println!("πŸ“¦ PRODUCT OPERATIONS");
265    println!("====================");
266
267    // Create products using the same executor/context
268    let products = vec![
269        ("Laptop Pro", 1299.99, "Electronics"),
270        ("Office Chair", 249.50, "Furniture"),
271        ("Coffee Mug", 12.99, "Kitchen"),
272    ];
273
274    let mut created_products = Vec::new();
275    for (name, price, category) in products {
276        match executor.execute(
277            CreateProduct,
278            &CreateProductProps {
279                name: name.to_string(),
280                price,
281                category: category.to_string(),
282            },
283        ) {
284            Ok(product) => {
285                println!(
286                    "βœ… Created product: {} (ID: {}, Price: ${:.2})",
287                    product.name, product.id, product.price
288                );
289                created_products.push(product);
290            }
291            Err(e) => {
292                println!("❌ Failed to create product {}: {:?}", name, e);
293                return;
294            }
295        }
296    }
297
298    println!(
299        "πŸ”’ Transaction count after product creation: {}\n",
300        executor.context().transaction_count()
301    );
302
303    // === Cross-Family Operations ===
304    println!("πŸ”„ CROSS-FAMILY LOOKUPS");
305    println!("=======================");
306
307    // Find users and products using the same context
308    // This demonstrates how the cache works across different API families
309
310    println!("πŸ” Looking up created entities...");
311
312    // Find first user
313    if let Some(user) = created_users.first() {
314        match executor.execute(FindUser, &FindUserProps { user_id: user.id }) {
315            Ok(found_user) => println!("πŸ‘€ Found user: {} ({})", found_user.name, found_user.email),
316            Err(e) => println!("❌ Failed to find user: {:?}", e),
317        }
318    }
319
320    // Find first product
321    if let Some(product) = created_products.first() {
322        match executor.execute(
323            FindProduct,
324            &FindProductProps {
325                product_id: product.id,
326            },
327        ) {
328            Ok(found_product) => println!(
329                "πŸ“¦ Found product: {} (${:.2})",
330                found_product.name, found_product.price
331            ),
332            Err(e) => println!("❌ Failed to find product: {:?}", e),
333        }
334    }
335
336    // === Context Inspection ===
337    println!("\nπŸ“Š CONTEXT INSPECTION");
338    println!("=====================");
339
340    let context = executor.context();
341    println!(
342        "πŸ”’ Final transaction count: {}",
343        context.transaction_count()
344    );
345    println!("πŸ’Ύ Cache entries: {} items", context.cache().len());
346
347    // Show cache contents
348    println!("πŸ“‹ Cached items:");
349    for (key, value) in context.cache().iter() {
350        // Truncate long values for display
351        let display_value = if value.len() > 50 {
352            format!("{}...", &value[..47])
353        } else {
354            value.clone()
355        };
356        println!("   β€’ {}: {}", key, display_value);
357    }
358
359    // === Executor Benefits Demo ===
360    println!("\nπŸ’‘ EXECUTOR BENEFITS");
361    println!("====================");
362
363    // Show how we can access the context for debugging or inspection
364    let final_context = executor.context();
365    println!("βœ… Centralized state management:");
366    println!(
367        "   β€’ {} total operations executed",
368        final_context.transaction_count()
369    );
370    println!("   β€’ {} entities cached", final_context.cache().len());
371    println!("   β€’ Single context shared across {} API families", 2);
372
373    println!("\nπŸŽ‰ Executor pattern example completed successfully!");
374    println!("πŸ’‘ Key advantages of ApiExecutor:");
375    println!("   β€’ Ergonomic API: executor.execute(Operation, &parameters)");
376    println!("   β€’ Centralized context management with owned context");
377    println!("   β€’ Consistent patterns across different API families");
378    println!("   β€’ Easy context inspection and debugging");
379    println!("   β€’ Efficient state sharing (cache, connections, etc.)");
380}
Source

pub fn context(&self) -> &C

Returns an immutable reference to the executor’s context.

Examples found in repository?
examples/executor_pattern.rs (line 221)
213fn main() {
214    println!("πŸ”§ ApiThing Executor Pattern Example");
215    println!("====================================\n");
216
217    // Create an executor that manages the context for us
218    let mut executor = ApiExecutor::new(AppContext::new("production_db".to_string()));
219
220    println!("πŸ—οΈ  Created ApiExecutor with context");
221    println!("πŸ“Š Connection: {}", executor.context().connection_pool());
222    println!(
223        "πŸ”’ Initial transaction count: {}\n",
224        executor.context().transaction_count()
225    );
226
227    // === User Operations ===
228    println!("πŸ‘₯ USER OPERATIONS");
229    println!("==================");
230
231    // Create multiple users using the executor
232    let users = vec![
233        ("Alice Johnson", "alice@company.com"),
234        ("Bob Smith", "bob@company.com"),
235        ("Carol Davis", "carol@company.com"),
236    ];
237
238    let mut created_users = Vec::new();
239    for (name, email) in users {
240        match executor.execute(
241            CreateUser,
242            &CreateUserProps {
243                name: name.to_string(),
244                email: email.to_string(),
245            },
246        ) {
247            Ok(user) => {
248                println!("βœ… Created user: {} (ID: {})", user.name, user.id);
249                created_users.push(user);
250            }
251            Err(e) => {
252                println!("❌ Failed to create user {}: {:?}", name, e);
253                return;
254            }
255        }
256    }
257
258    println!(
259        "πŸ”’ Transaction count after user creation: {}\n",
260        executor.context().transaction_count()
261    );
262
263    // === Product Operations (Same Context) ===
264    println!("πŸ“¦ PRODUCT OPERATIONS");
265    println!("====================");
266
267    // Create products using the same executor/context
268    let products = vec![
269        ("Laptop Pro", 1299.99, "Electronics"),
270        ("Office Chair", 249.50, "Furniture"),
271        ("Coffee Mug", 12.99, "Kitchen"),
272    ];
273
274    let mut created_products = Vec::new();
275    for (name, price, category) in products {
276        match executor.execute(
277            CreateProduct,
278            &CreateProductProps {
279                name: name.to_string(),
280                price,
281                category: category.to_string(),
282            },
283        ) {
284            Ok(product) => {
285                println!(
286                    "βœ… Created product: {} (ID: {}, Price: ${:.2})",
287                    product.name, product.id, product.price
288                );
289                created_products.push(product);
290            }
291            Err(e) => {
292                println!("❌ Failed to create product {}: {:?}", name, e);
293                return;
294            }
295        }
296    }
297
298    println!(
299        "πŸ”’ Transaction count after product creation: {}\n",
300        executor.context().transaction_count()
301    );
302
303    // === Cross-Family Operations ===
304    println!("πŸ”„ CROSS-FAMILY LOOKUPS");
305    println!("=======================");
306
307    // Find users and products using the same context
308    // This demonstrates how the cache works across different API families
309
310    println!("πŸ” Looking up created entities...");
311
312    // Find first user
313    if let Some(user) = created_users.first() {
314        match executor.execute(FindUser, &FindUserProps { user_id: user.id }) {
315            Ok(found_user) => println!("πŸ‘€ Found user: {} ({})", found_user.name, found_user.email),
316            Err(e) => println!("❌ Failed to find user: {:?}", e),
317        }
318    }
319
320    // Find first product
321    if let Some(product) = created_products.first() {
322        match executor.execute(
323            FindProduct,
324            &FindProductProps {
325                product_id: product.id,
326            },
327        ) {
328            Ok(found_product) => println!(
329                "πŸ“¦ Found product: {} (${:.2})",
330                found_product.name, found_product.price
331            ),
332            Err(e) => println!("❌ Failed to find product: {:?}", e),
333        }
334    }
335
336    // === Context Inspection ===
337    println!("\nπŸ“Š CONTEXT INSPECTION");
338    println!("=====================");
339
340    let context = executor.context();
341    println!(
342        "πŸ”’ Final transaction count: {}",
343        context.transaction_count()
344    );
345    println!("πŸ’Ύ Cache entries: {} items", context.cache().len());
346
347    // Show cache contents
348    println!("πŸ“‹ Cached items:");
349    for (key, value) in context.cache().iter() {
350        // Truncate long values for display
351        let display_value = if value.len() > 50 {
352            format!("{}...", &value[..47])
353        } else {
354            value.clone()
355        };
356        println!("   β€’ {}: {}", key, display_value);
357    }
358
359    // === Executor Benefits Demo ===
360    println!("\nπŸ’‘ EXECUTOR BENEFITS");
361    println!("====================");
362
363    // Show how we can access the context for debugging or inspection
364    let final_context = executor.context();
365    println!("βœ… Centralized state management:");
366    println!(
367        "   β€’ {} total operations executed",
368        final_context.transaction_count()
369    );
370    println!("   β€’ {} entities cached", final_context.cache().len());
371    println!("   β€’ Single context shared across {} API families", 2);
372
373    println!("\nπŸŽ‰ Executor pattern example completed successfully!");
374    println!("πŸ’‘ Key advantages of ApiExecutor:");
375    println!("   β€’ Ergonomic API: executor.execute(Operation, &parameters)");
376    println!("   β€’ Centralized context management with owned context");
377    println!("   β€’ Consistent patterns across different API families");
378    println!("   β€’ Easy context inspection and debugging");
379    println!("   β€’ Efficient state sharing (cache, connections, etc.)");
380}
Source

pub fn context_mut(&mut self) -> &mut C

Returns a mutable reference to the executor’s context.

Trait ImplementationsΒ§

SourceΒ§

impl<C: Clone> Clone for ApiExecutor<C>

SourceΒ§

fn clone(&self) -> ApiExecutor<C>

Returns a duplicate of the value. Read more
1.0.0 Β· SourceΒ§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
SourceΒ§

impl<C: Debug> Debug for ApiExecutor<C>

SourceΒ§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait ImplementationsΒ§

Β§

impl<C> Freeze for ApiExecutor<C>
where C: Freeze,

Β§

impl<C> RefUnwindSafe for ApiExecutor<C>
where C: RefUnwindSafe,

Β§

impl<C> Send for ApiExecutor<C>
where C: Send,

Β§

impl<C> Sync for ApiExecutor<C>
where C: Sync,

Β§

impl<C> Unpin for ApiExecutor<C>
where C: Unpin,

Β§

impl<C> UnwindSafe for ApiExecutor<C>
where C: UnwindSafe,

Blanket ImplementationsΒ§

SourceΒ§

impl<T> Any for T
where T: 'static + ?Sized,

SourceΒ§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
SourceΒ§

impl<T> Borrow<T> for T
where T: ?Sized,

SourceΒ§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
SourceΒ§

impl<T> BorrowMut<T> for T
where T: ?Sized,

SourceΒ§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
SourceΒ§

impl<T> CloneToUninit for T
where T: Clone,

SourceΒ§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

πŸ”¬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
SourceΒ§

impl<T> From<T> for T

SourceΒ§

fn from(t: T) -> T

Returns the argument unchanged.

SourceΒ§

impl<T, U> Into<U> for T
where U: From<T>,

SourceΒ§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

SourceΒ§

impl<T> ToOwned for T
where T: Clone,

SourceΒ§

type Owned = T

The resulting type after obtaining ownership.
SourceΒ§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
SourceΒ§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
SourceΒ§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

SourceΒ§

type Error = Infallible

The type returned in the event of a conversion error.
SourceΒ§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
SourceΒ§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

SourceΒ§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
SourceΒ§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.