mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 01:47:47 +08:00
refactor(workspace): enforce layered crate boundaries
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::RetryPolicy;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum TaskKind {
|
||||
Scheduled,
|
||||
Daemon,
|
||||
OnDemand,
|
||||
FireAndForget,
|
||||
}
|
||||
|
||||
impl TaskKind {
|
||||
pub const fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Scheduled => "scheduled",
|
||||
Self::Daemon => "daemon",
|
||||
Self::OnDemand => "on_demand",
|
||||
Self::FireAndForget => "fire_and_forget",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TaskDefinition {
|
||||
pub key: &'static str,
|
||||
pub kind: TaskKind,
|
||||
pub trigger: &'static str,
|
||||
pub singleton: bool,
|
||||
pub persist_history: bool,
|
||||
pub retry_policy: RetryPolicy,
|
||||
}
|
||||
|
||||
impl TaskDefinition {
|
||||
pub const fn new(
|
||||
key: &'static str,
|
||||
kind: TaskKind,
|
||||
trigger: &'static str,
|
||||
singleton: bool,
|
||||
persist_history: bool,
|
||||
retry_policy: RetryPolicy,
|
||||
) -> Self {
|
||||
Self {
|
||||
key,
|
||||
kind,
|
||||
trigger,
|
||||
singleton,
|
||||
persist_history,
|
||||
retry_policy,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn singleton(
|
||||
key: &'static str,
|
||||
kind: TaskKind,
|
||||
trigger: &'static str,
|
||||
persist_history: bool,
|
||||
retry_policy: RetryPolicy,
|
||||
) -> Self {
|
||||
Self::new(key, kind, trigger, true, persist_history, retry_policy)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FencingToken(u64);
|
||||
|
||||
impl FencingToken {
|
||||
pub const fn new(value: u64) -> Option<Self> {
|
||||
if value == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn get(self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
use crate::FencingToken;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TaskLease {
|
||||
pub task_key: String,
|
||||
pub owner: String,
|
||||
pub fencing_token: String,
|
||||
pub expires_at_unix_ms: u64,
|
||||
}
|
||||
|
||||
impl TaskLease {
|
||||
pub fn is_expired(&self, now_unix_ms: u64) -> bool {
|
||||
now_unix_ms >= self.expires_at_unix_ms
|
||||
}
|
||||
|
||||
pub fn parsed_fencing_token(&self) -> Result<FencingToken, TaskLeaseError> {
|
||||
self.fencing_token
|
||||
.parse::<u64>()
|
||||
.ok()
|
||||
.and_then(FencingToken::new)
|
||||
.ok_or(TaskLeaseError::InvalidFencingToken)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
|
||||
pub enum TaskLeaseError {
|
||||
#[error("task lease is unavailable")]
|
||||
Unavailable,
|
||||
#[error("task lease has expired")]
|
||||
Expired,
|
||||
#[error("task fencing token is invalid")]
|
||||
InvalidFencingToken,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::TaskLease;
|
||||
use crate::{RetryPolicy, TaskDefinition, TaskKind};
|
||||
|
||||
#[test]
|
||||
fn singleton_definition_expiry_and_fencing_are_explicit() {
|
||||
let definition = TaskDefinition::singleton(
|
||||
"cleanup",
|
||||
TaskKind::Scheduled,
|
||||
"interval",
|
||||
true,
|
||||
RetryPolicy::default(),
|
||||
);
|
||||
assert!(definition.singleton);
|
||||
let lease = TaskLease {
|
||||
task_key: "cleanup".to_string(),
|
||||
owner: "node-a".to_string(),
|
||||
fencing_token: "1".to_string(),
|
||||
expires_at_unix_ms: 10,
|
||||
};
|
||||
assert!(lease.is_expired(10));
|
||||
assert_eq!(lease.parsed_fencing_token().unwrap().get(), 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//! Runtime-independent task contracts.
|
||||
|
||||
mod definition;
|
||||
mod fencing;
|
||||
mod lease;
|
||||
mod retry;
|
||||
|
||||
pub use definition::{TaskDefinition, TaskKind};
|
||||
pub use fencing::FencingToken;
|
||||
pub use lease::{TaskLease, TaskLeaseError};
|
||||
pub use retry::RetryPolicy;
|
||||
@@ -0,0 +1,12 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RetryPolicy {
|
||||
pub max_attempts: u32,
|
||||
}
|
||||
|
||||
impl Default for RetryPolicy {
|
||||
fn default() -> Self {
|
||||
Self { max_attempts: 1 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user