1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use uuid::Uuid;

use crate::pretty_duration::PrettyDuration;

use super::{Entity, EntityDescriptorConst, WorkloadV2};

pub type JobId = Uuid;

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobSpecV1 {
    pub cronjob_id: Option<Uuid>,

    #[serde(flatten)]
    pub definition: JobDefinition,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobDefinition {
    /// Number of retries before the job is considered failed.
    ///
    /// Defaults to 0.
    pub max_retries: Option<u32>,

    /// Amount of time after the job is aborted and considered failed.
    ///
    /// Defaults to 1 hour.
    pub timeout: Option<PrettyDuration>,

    /// The thing executed by this cron job.
    ///
    /// May be either triggering an HTTP request to a given app, or running
    /// spawning a new instance.
    pub invoke: JobInvoke,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
#[allow(clippy::large_enum_variant)]
pub enum JobInvoke {
    Spawn(WorkloadV2),
    Fetch(JobInvokeFetch),
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobInvokeFetch {
    pub url: String,
    pub method: Option<super::HttpMethod>,
    pub headers: Option<HashMap<String, String>>,
    pub success_status_codes: Option<Vec<u16>>,
}

impl EntityDescriptorConst for JobSpecV1 {
    const NAMESPACE: &'static str = "wasmer.io";
    const NAME: &'static str = "JobResult";
    const VERSION: &'static str = "v1-alpha1";
    const KIND: &'static str = "wasmer.io/CronJob.v1-alpha1";
    type Spec = Self;
    type State = ();
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobStatusV1 {
    #[serde(with = "time::serde::timestamp::option")]
    #[schemars(with = "Option<u64>")]
    pub started_at: Option<OffsetDateTime>,
    #[serde(with = "time::serde::timestamp::option")]
    #[schemars(with = "Option<u64>")]
    pub finished_at: Option<OffsetDateTime>,

    pub success_invocation: Option<JobInvocation>,
    pub failed_invocations: Vec<JobInvocation>,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobInvocation {
    #[serde(with = "time::serde::timestamp")]
    #[schemars(with = "u64")]
    pub started_at: OffsetDateTime,
    #[serde(with = "time::serde::timestamp")]
    #[schemars(with = "u64")]
    pub finished_at: OffsetDateTime,
    pub success: bool,
    pub error: Option<String>,

    pub output: Option<JobInvocationOutput>,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub enum JobInvocationOutput {
    Spawn(JobInvocationOutputSpawn),
    Fetch(JobInvocationOutputFetch),
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobInvocationOutputSpawn {
    pub instance_id: Option<Uuid>,
    pub exit_code: Option<i32>,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, schemars::JsonSchema)]
pub struct JobInvocationOutputFetch {
    pub status_code: Option<u16>,
    pub body: Option<String>,
    pub request_id: Option<Uuid>,
}

pub type Job = Entity<JobSpecV1>;