pub struct Service { /* private fields */ }Expand description
Genetic algorithm optimization service that manages the entire optimization lifecycle. Handles request creation, population generation, genotype evaluation, and breeding.
Implementations§
Source§impl Service
impl Service
Sourcepub async fn new_optimization_request(
&self,
type_name: &str,
type_hash: i32,
goal: FitnessGoal,
schedule: Schedule,
selector: Selector,
mutagen: Mutagen,
crossover: Crossover,
distribution: Distribution,
data: Option<impl Serialize + Send + Sync>,
) -> Result<Uuid, Error>
pub async fn new_optimization_request( &self, type_name: &str, type_hash: i32, goal: FitnessGoal, schedule: Schedule, selector: Selector, mutagen: Mutagen, crossover: Crossover, distribution: Distribution, data: Option<impl Serialize + Send + Sync>, ) -> Result<Uuid, Error>
Creates a new genetic algorithm optimization request.
This is the main entry point for starting genetic algorithm optimization. It configures and initiates an evolutionary process that will attempt to find optimal solutions for your problem type.
§Parameters
type_name- Human-readable name of the type being optimized (fromEncodeable::NAME)type_hash- Unique hash identifying the type structure (fromEncodeable::HASH)goal- Optimization objective and stopping criteriaschedule- Controls generation timing and population lifecycleselector- Parent selection strategy for breeding operationsmutagen- Mutation behavior including temperature and rate schedulescrossover- Genetic recombination method for combining parentsdistribution- Initial population generation strategy
§Optimization Goal
The goal parameter defines when optimization should stop:
FitnessGoal::maximize(0.95)- Stop when fitness reaches 95% or higherFitnessGoal::minimize(0.1)- Stop when fitness drops to 10% or lower
§Population Management
The schedule controls generation timing and resource allocation:
Schedule::generational(100, 50)- 100 generations, 50 individuals eachSchedule::rolling(5000, 100, 10)- 5000 total evaluations, 100 max population, breed 10 at a time
§Parent Selection
The selector determines how parents are chosen for breeding:
Selector::tournament(3, 100)- Tournament selection (size 3) from 100 candidatesSelector::roulette(100)- Fitness-proportionate selection from 100 candidates
§Mutation Strategy
The mutagen combines temperature (step size) and mutation rate (frequency):
Mutagen::constant(0.5, 0.3)- Fixed 50% temperature, 30% mutation rate- Adaptive strategies use
Temperature::linear()andMutationRate::exponential()
§Genetic Recombination
The crossover method combines genetic material from parents:
Crossover::uniform(0.5)- Each gene has 50% chance from first parentCrossover::single_point()- Cut genome at random point, swap tails
§Initial Population
The distribution strategy affects initial diversity and convergence:
Distribution::latin_hypercube(50)- Structured sampling for better coverageDistribution::random(50)- Pure random sampling
§Common Configurations
§Quick Convergence (Time-Constrained)
use fx_durable_ga::models::*;
service.new_optimization_request(
MyType::NAME,
MyType::HASH,
FitnessGoal::maximize(0.90)?, // Modest target
Schedule::generational(20, 30), // Small, fast generations
Selector::tournament(5, 50)?, // Strong selection pressure
Mutagen::new(
Temperature::exponential(0.8, 0.1, 1.2, 3)?, // Rapid cooling
MutationRate::exponential(0.6, 0.05, 1.1, 2)?
),
Crossover::uniform(0.6)?, // High recombination
Distribution::latin_hypercube(30),
None::<()>,
).await?;§Balanced Search (General Purpose)
use fx_durable_ga::models::*;
service.new_optimization_request(
MyType::NAME,
MyType::HASH,
FitnessGoal::maximize(0.95)?, // High-quality target
Schedule::generational(50, 50), // Moderate generations
Selector::tournament(3, 100)?, // Balanced selection
Mutagen::new(
Temperature::linear(0.7, 0.2, 1.0)?, // Gradual cooling
MutationRate::linear(0.4, 0.1, 1.0)?
),
Crossover::uniform(0.5)?, // Balanced recombination
Distribution::latin_hypercube(50),
None::<()>,
).await?;§Thorough Exploration (Complex Problems)
use fx_durable_ga::models::*;
service.new_optimization_request(
MyType::NAME,
MyType::HASH,
FitnessGoal::maximize(0.99)?, // High precision target
Schedule::rolling(10000, 200, 20), // Large budget
Selector::tournament(2, 150)?, // Low selection pressure
Mutagen::constant(0.6, 0.4)?, // Sustained exploration
Crossover::single_point(), // Conservative recombination
Distribution::latin_hypercube(100), // High initial diversity
None::<()>,
).await?;§Parameter Interactions
Key relationships to consider:
- High selection pressure + Low mutation: Fast convergence, may get stuck
- Low selection pressure + High mutation: Slow convergence, good exploration
- Large populations + Tournament selection: Better genetic diversity
- Small populations + Roulette selection: Risk of premature convergence
- Exponential decay + Generational schedule: Classic simulated annealing
- Linear decay + Rolling schedule: Steady refinement over time
§Returns
Returns Ok(()) if the optimization request was successfully created and scheduled.
The actual optimization runs asynchronously via the event/job system.
§Errors
- Returns error if the specified type hasn’t been registered with an evaluator
- Returns error if database operations fail
- Parameter validation errors are caught at construction time (e.g.,
FitnessGoal::maximize(1.5)fails)
§Example Usage
use fx_durable_ga::models::*;
// Define your problem type
#[derive(Debug)]
struct Point { x: f64, y: f64 }
impl Encodeable for Point {
const NAME: &'static str = "Point";
type Phenotype = Point;
fn morphology() -> Vec<GeneBounds> {
vec![
GeneBounds::decimal(0.0, 10.0, 1000, 3).unwrap(),
GeneBounds::decimal(0.0, 10.0, 1000, 3).unwrap(),
]
}
fn encode(&self) -> Vec<i64> {
let bounds = Self::morphology();
vec![
bounds[0].from_sample(self.x / 10.0),
bounds[1].from_sample(self.y / 10.0),
]
}
fn decode(genes: &[i64]) -> Self::Phenotype {
let bounds = Self::morphology();
Point {
x: bounds[0].decode_f64(genes[0]),
y: bounds[1].decode_f64(genes[1]),
}
}
}
// Start optimization
service.new_optimization_request(
Point::NAME,
Point::HASH,
FitnessGoal::maximize(0.95)?,
Schedule::generational(50, 50),
Selector::tournament(3, 100)?,
Mutagen::constant(0.5, 0.3)?,
Crossover::uniform(0.5)?,
Distribution::latin_hypercube(50),
None::<()>,
).await?;Examples found in repository?
195async fn main() -> Result<()> {
196 dotenv::from_filename(".env.local").ok();
197 tracing_subscriber::fmt()
198 .pretty()
199 .with_thread_ids(true)
200 .with_max_level(Level::INFO)
201 .init();
202
203 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
204 let pool = PgPoolOptions::new()
205 .max_connections(10)
206 .connect(&database_url)
207 .await?;
208
209 // Run all default migrations
210 fx_durable_ga::migrations::run_default_migrations(&pool).await?;
211
212 let service = Arc::new(
213 bootstrap(pool.clone())
214 .await?
215 .register::<NeuralArchitecture, _>(ArchitectureEvaluator)
216 .await?
217 .build(),
218 );
219
220 let mut registry = fx_event_bus::EventHandlerRegistry::new();
221 register_event_handlers(
222 Arc::new(Queries::new(FX_MQ_JOBS_SCHEMA_NAME)),
223 service.clone(),
224 &mut registry,
225 );
226 let mut listener = fx_event_bus::Listener::new(pool.clone(), registry);
227 tokio::spawn(async move { listener.listen(None).await });
228
229 let host_id = Uuid::parse_str("00000000-0000-0000-0000-123456789abc")?;
230 let mut jobs_listener = fx_mq_jobs::Listener::new(
231 pool.clone(),
232 register_job_handlers(&service, fx_mq_jobs::RegistryBuilder::new()),
233 WORKERS,
234 host_id,
235 Duration::from_secs(600),
236 )
237 .await?;
238 tokio::spawn(async move { jobs_listener.listen().await });
239
240 service
241 .new_optimization_request(
242 NeuralArchitecture::NAME,
243 NeuralArchitecture::HASH,
244 FitnessGoal::minimize(FITNESS_TARGET)?,
245 Schedule::generational(10, 10),
246 Selector::tournament(5, 15)?,
247 Mutagen::new(Temperature::constant(0.8)?, MutationRate::constant(0.4)?),
248 Crossover::uniform(0.5)?,
249 Distribution::latin_hypercube(15),
250 None::<()>,
251 )
252 .await?;
253
254 tokio::time::sleep(Duration::from_secs(3600)).await;
255 Ok(())
256}More examples
130async fn main() -> Result<()> {
131 dotenv::from_filename(".env.local").ok();
132
133 // Initialize logging to see optimization progress
134 tracing_subscriber::fmt()
135 .with_max_level(tracing::Level::INFO)
136 .init();
137
138 // Database setup - genetic algorithms need persistent storage for populations
139 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
140 let pool = PgPoolOptions::new()
141 .max_connections(50)
142 .connect(&database_url)
143 .await?;
144
145 fx_event_bus::run_migrations(&pool).await?;
146 fx_mq_jobs::run_migrations(&pool, fx_mq_jobs::FX_MQ_JOBS_SCHEMA_NAME).await?;
147
148 // Bootstrap the optimization service and register our problem type
149 let target_point = Point {
150 x: 1.0,
151 y: 1.5,
152 z: 2.5,
153 }; // Target point to find
154 let evaluator = PointDistanceEvaluator { target_point };
155 let service = Arc::new(
156 bootstrap(pool.clone())
157 .await?
158 .register::<Point, _>(evaluator)
159 .await?
160 .build(),
161 );
162
163 // setup event handling and spawn an event handling agent
164 let mut registry = fx_event_bus::EventHandlerRegistry::new();
165 register_event_handlers(
166 Arc::new(Queries::new(FX_MQ_JOBS_SCHEMA_NAME)),
167 service.clone(),
168 &mut registry,
169 );
170 let mut listener = fx_event_bus::Listener::new(pool.clone(), registry);
171 let _events_handle = tokio::spawn(async move {
172 listener.listen(None).await?;
173 Ok::<(), sqlx::Error>(())
174 });
175
176 // setup job handling and initiate workers
177 let host_id = Uuid::parse_str("ba3a4752-c4ce-4129-aa1d-55a0b2107e68").expect("valid uuid");
178 let hold_for = Duration::from_secs(TIMEOUT_SECONDS);
179 let mut jobs_listener = fx_mq_jobs::Listener::new(
180 pool.clone(),
181 register_job_handlers(&service, fx_mq_jobs::RegistryBuilder::new()),
182 8,
183 host_id,
184 hold_for,
185 )
186 .await?;
187 let _jobs_handle = tokio::spawn(async move {
188 jobs_listener.listen().await?;
189 Ok::<(), anyhow::Error>(())
190 });
191
192 // Create multiple optimization requests with different genetic algorithm parameters
193 for _ in 0..1 {
194 service
195 .new_optimization_request(
196 Point::NAME,
197 Point::HASH,
198 FitnessGoal::minimize(0.01)?, // Stop when distance ≤ 0.01
199 Schedule::generational(200, 30),
200 Selector::tournament(7, 100)?,
201 Mutagen::new(Temperature::constant(0.7)?, MutationRate::constant(0.3)?),
202 Crossover::uniform(0.5)?,
203 Distribution::latin_hypercube(1000),
204 None::<()>,
205 )
206 .await?;
207 }
208
209 let timeout_duration = Duration::from_secs(TIMEOUT_SECONDS);
210 let start_time = std::time::Instant::now();
211
212 loop {
213 tokio::time::sleep(Duration::from_secs(1)).await;
214
215 // Check if we've exceeded the timeout
216 if start_time.elapsed() >= timeout_duration {
217 println!(
218 "Timeout reached after {} seconds. Stopping optimization.",
219 timeout_duration.as_secs()
220 );
221 break;
222 }
223 }
224
225 Ok(())
226}377async fn main() -> Result<()> {
378 dotenv::from_filename(".env.local").ok();
379 tracing_subscriber::fmt()
380 .pretty()
381 .with_thread_ids(true)
382 .with_max_level(Level::INFO)
383 .init();
384
385 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
386 let pool = PgPoolOptions::new()
387 .max_connections(10)
388 .connect(&database_url)
389 .await?;
390
391 // Run all default migrations
392 fx_durable_ga::migrations::run_default_migrations(&pool).await?;
393
394 let service = Arc::new(
395 bootstrap(pool.clone())
396 .await?
397 .register::<FeatureConfig, _>(FeatureEvaluator)
398 .await?
399 .build(),
400 );
401
402 let mut registry = fx_event_bus::EventHandlerRegistry::new();
403 register_event_handlers(
404 Arc::new(Queries::new(FX_MQ_JOBS_SCHEMA_NAME)),
405 service.clone(),
406 &mut registry,
407 );
408 let mut listener = fx_event_bus::Listener::new(pool.clone(), registry);
409 tokio::spawn(async move { listener.listen(None).await });
410
411 let host_id = Uuid::parse_str("00000000-0000-0000-0000-123456789abc")?;
412 let mut jobs_listener = fx_mq_jobs::Listener::new(
413 pool.clone(),
414 register_job_handlers(&service, fx_mq_jobs::RegistryBuilder::new()),
415 WORKERS,
416 host_id,
417 Duration::from_secs(600),
418 )
419 .await?;
420 tokio::spawn(async move { jobs_listener.listen().await });
421
422 let request_id = service
423 .new_optimization_request(
424 FeatureConfig::NAME,
425 FeatureConfig::HASH,
426 FitnessGoal::minimize(FITNESS_TARGET)?,
427 Schedule::generational(40, 10),
428 Selector::tournament(5, 45)?,
429 Mutagen::new(Temperature::constant(0.7)?, MutationRate::constant(0.35)?),
430 Crossover::uniform(0.5)?,
431 Distribution::latin_hypercube(40),
432 None::<()>,
433 )
434 .await?;
435
436 // Poll for completion every 15 seconds (timeout after 1 hour)
437 let timeout = Duration::from_secs(7200);
438 let poll_interval = Duration::from_secs(15);
439 let start = std::time::Instant::now();
440
441 loop {
442 if service.is_request_concluded(request_id).await? {
443 println!("\nOptimization completed!");
444 break;
445 }
446
447 if start.elapsed() > timeout {
448 println!("\nOptimization timed out after 1 hour.");
449 break;
450 }
451
452 tokio::time::sleep(poll_interval).await;
453 }
454
455 // Get and print the best configuration
456 if let Some((genotype, fitness)) = service.get_best_genotype(request_id).await? {
457 let config = FeatureConfig::decode(&genotype.genome());
458 println!("\n=== Best Configuration ===");
459 println!("Fitness (MSE): {:.6}", fitness);
460 println!("RMSE: {:.6}°C", fitness.sqrt());
461 println!("\nHyperparameters:");
462 println!(" Hidden Size: {}", config.hidden_size);
463 println!(" Learning Rate: {}", config.learning_rate);
464 println!(" Sequence Length: {}", config.sequence_length);
465 println!("\nFeatures:");
466 for (i, feature) in config.features.iter().enumerate() {
467 let pipeline = feature
468 .transforms
469 .iter()
470 .map(|t| t.to_string())
471 .collect::<Vec<_>>()
472 .join(" → ");
473 if pipeline.is_empty() {
474 println!(" feat_{}: {}", i, feature.source);
475 } else {
476 println!(" feat_{}: {} → {}", i, feature.source, pipeline);
477 }
478 }
479 } else {
480 println!("No genotypes were evaluated.");
481 }
482
483 Ok(())
484}Sourcepub async fn interrupt_request(&self, request_id: Uuid) -> Result<(), Error>
pub async fn interrupt_request(&self, request_id: Uuid) -> Result<(), Error>
Interrupts a running optimization request. Publishes an interruption event that concludes the request with the “Interrupted” reason.
Sourcepub async fn get_best_genotype(
&self,
request_id: Uuid,
) -> Result<Option<(Genotype, f64)>, Error>
pub async fn get_best_genotype( &self, request_id: Uuid, ) -> Result<Option<(Genotype, f64)>, Error>
Gets the best genotype for a request based on fitness. Returns the genotype with the best (min or max) fitness depending on the goal.
Examples found in repository?
377async fn main() -> Result<()> {
378 dotenv::from_filename(".env.local").ok();
379 tracing_subscriber::fmt()
380 .pretty()
381 .with_thread_ids(true)
382 .with_max_level(Level::INFO)
383 .init();
384
385 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
386 let pool = PgPoolOptions::new()
387 .max_connections(10)
388 .connect(&database_url)
389 .await?;
390
391 // Run all default migrations
392 fx_durable_ga::migrations::run_default_migrations(&pool).await?;
393
394 let service = Arc::new(
395 bootstrap(pool.clone())
396 .await?
397 .register::<FeatureConfig, _>(FeatureEvaluator)
398 .await?
399 .build(),
400 );
401
402 let mut registry = fx_event_bus::EventHandlerRegistry::new();
403 register_event_handlers(
404 Arc::new(Queries::new(FX_MQ_JOBS_SCHEMA_NAME)),
405 service.clone(),
406 &mut registry,
407 );
408 let mut listener = fx_event_bus::Listener::new(pool.clone(), registry);
409 tokio::spawn(async move { listener.listen(None).await });
410
411 let host_id = Uuid::parse_str("00000000-0000-0000-0000-123456789abc")?;
412 let mut jobs_listener = fx_mq_jobs::Listener::new(
413 pool.clone(),
414 register_job_handlers(&service, fx_mq_jobs::RegistryBuilder::new()),
415 WORKERS,
416 host_id,
417 Duration::from_secs(600),
418 )
419 .await?;
420 tokio::spawn(async move { jobs_listener.listen().await });
421
422 let request_id = service
423 .new_optimization_request(
424 FeatureConfig::NAME,
425 FeatureConfig::HASH,
426 FitnessGoal::minimize(FITNESS_TARGET)?,
427 Schedule::generational(40, 10),
428 Selector::tournament(5, 45)?,
429 Mutagen::new(Temperature::constant(0.7)?, MutationRate::constant(0.35)?),
430 Crossover::uniform(0.5)?,
431 Distribution::latin_hypercube(40),
432 None::<()>,
433 )
434 .await?;
435
436 // Poll for completion every 15 seconds (timeout after 1 hour)
437 let timeout = Duration::from_secs(7200);
438 let poll_interval = Duration::from_secs(15);
439 let start = std::time::Instant::now();
440
441 loop {
442 if service.is_request_concluded(request_id).await? {
443 println!("\nOptimization completed!");
444 break;
445 }
446
447 if start.elapsed() > timeout {
448 println!("\nOptimization timed out after 1 hour.");
449 break;
450 }
451
452 tokio::time::sleep(poll_interval).await;
453 }
454
455 // Get and print the best configuration
456 if let Some((genotype, fitness)) = service.get_best_genotype(request_id).await? {
457 let config = FeatureConfig::decode(&genotype.genome());
458 println!("\n=== Best Configuration ===");
459 println!("Fitness (MSE): {:.6}", fitness);
460 println!("RMSE: {:.6}°C", fitness.sqrt());
461 println!("\nHyperparameters:");
462 println!(" Hidden Size: {}", config.hidden_size);
463 println!(" Learning Rate: {}", config.learning_rate);
464 println!(" Sequence Length: {}", config.sequence_length);
465 println!("\nFeatures:");
466 for (i, feature) in config.features.iter().enumerate() {
467 let pipeline = feature
468 .transforms
469 .iter()
470 .map(|t| t.to_string())
471 .collect::<Vec<_>>()
472 .join(" → ");
473 if pipeline.is_empty() {
474 println!(" feat_{}: {}", i, feature.source);
475 } else {
476 println!(" feat_{}: {} → {}", i, feature.source, pipeline);
477 }
478 }
479 } else {
480 println!("No genotypes were evaluated.");
481 }
482
483 Ok(())
484}Sourcepub async fn is_request_concluded(
&self,
request_id: Uuid,
) -> Result<bool, Error>
pub async fn is_request_concluded( &self, request_id: Uuid, ) -> Result<bool, Error>
Checks if an optimization request has concluded. Returns true if the request has been completed or terminated.
Examples found in repository?
377async fn main() -> Result<()> {
378 dotenv::from_filename(".env.local").ok();
379 tracing_subscriber::fmt()
380 .pretty()
381 .with_thread_ids(true)
382 .with_max_level(Level::INFO)
383 .init();
384
385 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
386 let pool = PgPoolOptions::new()
387 .max_connections(10)
388 .connect(&database_url)
389 .await?;
390
391 // Run all default migrations
392 fx_durable_ga::migrations::run_default_migrations(&pool).await?;
393
394 let service = Arc::new(
395 bootstrap(pool.clone())
396 .await?
397 .register::<FeatureConfig, _>(FeatureEvaluator)
398 .await?
399 .build(),
400 );
401
402 let mut registry = fx_event_bus::EventHandlerRegistry::new();
403 register_event_handlers(
404 Arc::new(Queries::new(FX_MQ_JOBS_SCHEMA_NAME)),
405 service.clone(),
406 &mut registry,
407 );
408 let mut listener = fx_event_bus::Listener::new(pool.clone(), registry);
409 tokio::spawn(async move { listener.listen(None).await });
410
411 let host_id = Uuid::parse_str("00000000-0000-0000-0000-123456789abc")?;
412 let mut jobs_listener = fx_mq_jobs::Listener::new(
413 pool.clone(),
414 register_job_handlers(&service, fx_mq_jobs::RegistryBuilder::new()),
415 WORKERS,
416 host_id,
417 Duration::from_secs(600),
418 )
419 .await?;
420 tokio::spawn(async move { jobs_listener.listen().await });
421
422 let request_id = service
423 .new_optimization_request(
424 FeatureConfig::NAME,
425 FeatureConfig::HASH,
426 FitnessGoal::minimize(FITNESS_TARGET)?,
427 Schedule::generational(40, 10),
428 Selector::tournament(5, 45)?,
429 Mutagen::new(Temperature::constant(0.7)?, MutationRate::constant(0.35)?),
430 Crossover::uniform(0.5)?,
431 Distribution::latin_hypercube(40),
432 None::<()>,
433 )
434 .await?;
435
436 // Poll for completion every 15 seconds (timeout after 1 hour)
437 let timeout = Duration::from_secs(7200);
438 let poll_interval = Duration::from_secs(15);
439 let start = std::time::Instant::now();
440
441 loop {
442 if service.is_request_concluded(request_id).await? {
443 println!("\nOptimization completed!");
444 break;
445 }
446
447 if start.elapsed() > timeout {
448 println!("\nOptimization timed out after 1 hour.");
449 break;
450 }
451
452 tokio::time::sleep(poll_interval).await;
453 }
454
455 // Get and print the best configuration
456 if let Some((genotype, fitness)) = service.get_best_genotype(request_id).await? {
457 let config = FeatureConfig::decode(&genotype.genome());
458 println!("\n=== Best Configuration ===");
459 println!("Fitness (MSE): {:.6}", fitness);
460 println!("RMSE: {:.6}°C", fitness.sqrt());
461 println!("\nHyperparameters:");
462 println!(" Hidden Size: {}", config.hidden_size);
463 println!(" Learning Rate: {}", config.learning_rate);
464 println!(" Sequence Length: {}", config.sequence_length);
465 println!("\nFeatures:");
466 for (i, feature) in config.features.iter().enumerate() {
467 let pipeline = feature
468 .transforms
469 .iter()
470 .map(|t| t.to_string())
471 .collect::<Vec<_>>()
472 .join(" → ");
473 if pipeline.is_empty() {
474 println!(" feat_{}: {}", i, feature.source);
475 } else {
476 println!(" feat_{}: {} → {}", i, feature.source, pipeline);
477 }
478 }
479 } else {
480 println!("No genotypes were evaluated.");
481 }
482
483 Ok(())
484}Sourcepub async fn search_genotypes(
&self,
filter: &Filter,
limit: i64,
) -> Result<Vec<(Genotype, Option<f64>)>, Error>
pub async fn search_genotypes( &self, filter: &Filter, limit: i64, ) -> Result<Vec<(Genotype, Option<f64>)>, Error>
Get a morphology by its type name
Sourcepub async fn get_phenotype<T: Encodeable>(
&self,
genotype_id: &Uuid,
) -> Result<T::Phenotype, Error>
pub async fn get_phenotype<T: Encodeable>( &self, genotype_id: &Uuid, ) -> Result<T::Phenotype, Error>
Get a phenotype by its type name
Auto Trait Implementations§
impl !RefUnwindSafe for Service
impl !UnwindSafe for Service
impl Freeze for Service
impl Send for Service
impl Sync for Service
impl Unpin for Service
impl UnsafeUnpin for Service
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more