ora-client 0.11.2

Part of the Ora scheduler framework.
Documentation
use std::time::SystemTime;

use crate::{
    job_definition::{JobDefinition, RetryPolicy, TimeoutBaseTime, TimeoutPolicy},
    schedule_definition::{
        ScheduleDefinition, ScheduleDetails, ScheduleJobCreationPolicy, ScheduleJobTimingPolicy,
        ScheduleJobTimingPolicyCron, ScheduleJobTimingPolicyRepeat, ScheduleMissedTimePolicy,
        ScheduleTimeRange,
    },
};
use eyre::OptionExt;
use ora_proto::{common::v1, server::v1::Schedule};

impl From<v1::JobTimeoutPolicy> for TimeoutPolicy {
    fn from(policy: v1::JobTimeoutPolicy) -> Self {
        Self {
            timeout: policy.timeout.and_then(|d| d.try_into().ok()),
            base_time: policy.base_time().into(),
        }
    }
}

impl From<TimeoutPolicy> for v1::JobTimeoutPolicy {
    fn from(policy: TimeoutPolicy) -> Self {
        Self {
            timeout: policy.timeout.and_then(|v| v.try_into().ok()),
            base_time: v1::JobTimeoutBaseTime::from(policy.base_time).into(),
        }
    }
}

impl From<v1::JobTimeoutBaseTime> for TimeoutBaseTime {
    fn from(base_time: v1::JobTimeoutBaseTime) -> Self {
        match base_time {
            v1::JobTimeoutBaseTime::Unspecified | v1::JobTimeoutBaseTime::StartTime => {
                Self::StartTime
            }
            v1::JobTimeoutBaseTime::TargetExecutionTime => Self::TargetExecutionTime,
        }
    }
}

impl From<TimeoutBaseTime> for v1::JobTimeoutBaseTime {
    fn from(base_time: TimeoutBaseTime) -> Self {
        match base_time {
            TimeoutBaseTime::StartTime => v1::JobTimeoutBaseTime::StartTime,
            TimeoutBaseTime::TargetExecutionTime => v1::JobTimeoutBaseTime::TargetExecutionTime,
        }
    }
}

impl From<v1::JobRetryPolicy> for RetryPolicy {
    fn from(policy: v1::JobRetryPolicy) -> Self {
        Self {
            retries: policy.retries,
        }
    }
}

impl From<RetryPolicy> for v1::JobRetryPolicy {
    fn from(policy: RetryPolicy) -> Self {
        Self {
            retries: policy.retries,
        }
    }
}

impl From<JobDefinition> for v1::JobDefinition {
    fn from(definition: JobDefinition) -> Self {
        Self {
            job_type_id: definition.job_type_id.into(),
            target_execution_time: Some(definition.target_execution_time.into()),
            input_payload_json: definition.input_payload_json,
            labels: definition
                .labels
                .into_iter()
                .map(|(key, value)| v1::JobLabel { key, value })
                .collect(),
            timeout_policy: Some(definition.timeout_policy.into()),
            retry_policy: Some(definition.retry_policy.into()),
            metadata_json: definition.metadata_json,
        }
    }
}

impl From<v1::JobDefinition> for JobDefinition {
    fn from(definition: v1::JobDefinition) -> Self {
        Self {
            job_type_id: definition.job_type_id.into(),
            target_execution_time: definition
                .target_execution_time
                .and_then(|t| SystemTime::try_from(t).ok())
                .unwrap_or(SystemTime::UNIX_EPOCH),
            input_payload_json: definition.input_payload_json,
            labels: definition
                .labels
                .into_iter()
                .map(|label| (label.key, label.value))
                .collect(),
            timeout_policy: definition.timeout_policy.unwrap_or_default().into(),
            retry_policy: definition.retry_policy.unwrap_or_default().into(),
            metadata_json: definition.metadata_json,
        }
    }
}

impl From<ScheduleDefinition> for v1::ScheduleDefinition {
    fn from(definition: ScheduleDefinition) -> Self {
        Self {
            job_timing_policy: Some(definition.job_timing_policy.into()),
            job_creation_policy: Some(match definition.job_creation_policy {
                ScheduleJobCreationPolicy::JobDefinition(job_definition) => {
                    v1::ScheduleJobCreationPolicy {
                        job_creation: Some(
                            v1::schedule_job_creation_policy::JobCreation::JobDefinition(
                                job_definition.into(),
                            ),
                        ),
                    }
                }
            }),
            labels: definition
                .labels
                .into_iter()
                .map(|(key, value)| v1::ScheduleLabel { key, value })
                .collect(),
            time_range: definition.time_range.map(Into::into),
            metadata_json: definition.metadata_json,
        }
    }
}

impl From<v1::TimeRange> for ScheduleTimeRange {
    fn from(time_range: v1::TimeRange) -> Self {
        Self {
            start: time_range
                .start
                .and_then(|start_time| start_time.try_into().ok()),
            end: time_range.end.and_then(|end_time| end_time.try_into().ok()),
        }
    }
}

impl From<ScheduleTimeRange> for v1::TimeRange {
    fn from(time_range: ScheduleTimeRange) -> Self {
        Self {
            start: time_range.start.map(Into::into),
            end: time_range.end.map(Into::into),
        }
    }
}

impl From<ScheduleJobTimingPolicy> for v1::ScheduleJobTimingPolicy {
    fn from(policy: ScheduleJobTimingPolicy) -> Self {
        match policy {
            ScheduleJobTimingPolicy::Repeat(scheduling_policy_repeat) => {
                v1::ScheduleJobTimingPolicy {
                    job_timing: Some(v1::schedule_job_timing_policy::JobTiming::Repeat(
                        v1::ScheduleJobTimingPolicyRepeat {
                            interval: Some(scheduling_policy_repeat.interval.try_into().unwrap()),
                            immediate: scheduling_policy_repeat.immediate,
                            missed_time_policy: v1::ScheduleMissedTimePolicy::from(
                                scheduling_policy_repeat.missed_time_policy,
                            )
                            .into(),
                        },
                    )),
                }
            }
            ScheduleJobTimingPolicy::Cron(scheduling_policy_cron) => v1::ScheduleJobTimingPolicy {
                job_timing: Some(v1::schedule_job_timing_policy::JobTiming::Cron(
                    v1::ScheduleJobTimingPolicyCron {
                        cron_expression: scheduling_policy_cron.cron_expression,
                        immediate: scheduling_policy_cron.immediate,
                        missed_time_policy: v1::ScheduleMissedTimePolicy::from(
                            scheduling_policy_cron.missed_time_policy,
                        )
                        .into(),
                    },
                )),
            },
        }
    }
}

impl TryFrom<v1::ScheduleJobTimingPolicy> for ScheduleJobTimingPolicy {
    type Error = eyre::Report;

    fn try_from(policy: v1::ScheduleJobTimingPolicy) -> eyre::Result<Self> {
        Ok(match policy.job_timing.ok_or_eyre("missing job timing")? {
            v1::schedule_job_timing_policy::JobTiming::Repeat(scheduling_policy_repeat) => {
                ScheduleJobTimingPolicy::Repeat(ScheduleJobTimingPolicyRepeat {
                    missed_time_policy: scheduling_policy_repeat.missed_time_policy().into(),
                    interval: scheduling_policy_repeat
                        .interval
                        .ok_or_eyre("missing schedule policy interval")?
                        .try_into()?,
                    immediate: scheduling_policy_repeat.immediate,
                })
            }
            v1::schedule_job_timing_policy::JobTiming::Cron(scheduling_policy_cron) => {
                ScheduleJobTimingPolicy::Cron(ScheduleJobTimingPolicyCron {
                    missed_time_policy: scheduling_policy_cron.missed_time_policy().into(),
                    cron_expression: scheduling_policy_cron.cron_expression,
                    immediate: scheduling_policy_cron.immediate,
                })
            }
        })
    }
}

impl From<ScheduleMissedTimePolicy> for v1::ScheduleMissedTimePolicy {
    fn from(policy: ScheduleMissedTimePolicy) -> Self {
        match policy {
            ScheduleMissedTimePolicy::Skip => Self::Skip,
            ScheduleMissedTimePolicy::Create => Self::Create,
        }
    }
}

impl From<v1::ScheduleMissedTimePolicy> for ScheduleMissedTimePolicy {
    fn from(policy: v1::ScheduleMissedTimePolicy) -> Self {
        match policy {
            v1::ScheduleMissedTimePolicy::Skip | v1::ScheduleMissedTimePolicy::Unspecified => {
                Self::Skip
            }
            v1::ScheduleMissedTimePolicy::Create => Self::Create,
        }
    }
}

impl From<ScheduleJobCreationPolicy> for v1::ScheduleJobCreationPolicy {
    fn from(policy: ScheduleJobCreationPolicy) -> Self {
        match policy {
            ScheduleJobCreationPolicy::JobDefinition(job_definition) => Self {
                job_creation: Some(
                    v1::schedule_job_creation_policy::JobCreation::JobDefinition(
                        job_definition.into(),
                    ),
                ),
            },
        }
    }
}

impl TryFrom<v1::ScheduleJobCreationPolicy> for ScheduleJobCreationPolicy {
    type Error = eyre::Report;

    fn try_from(policy: v1::ScheduleJobCreationPolicy) -> eyre::Result<Self> {
        Ok(
            match policy.job_creation.ok_or_eyre("missing job creation")? {
                v1::schedule_job_creation_policy::JobCreation::JobDefinition(job_definition) => {
                    ScheduleJobCreationPolicy::JobDefinition(job_definition.into())
                }
            },
        )
    }
}

impl TryFrom<Schedule> for ScheduleDetails {
    type Error = eyre::Report;

    fn try_from(schedule: Schedule) -> eyre::Result<Self> {
        let schedule_definition = schedule
            .definition
            .ok_or_eyre("missing schedule definition")?;

        Ok(Self {
            id: schedule.id.parse()?,
            created_at: SystemTime::try_from(
                schedule.created_at.ok_or_eyre("missing created_at")?,
            )?,
            cancelled: schedule.cancelled,
            active: schedule.active,
            job_timing_policy: schedule_definition
                .job_timing_policy
                .ok_or_eyre("missing job timing policy")?
                .try_into()?,
            job_creation_policy: schedule_definition
                .job_creation_policy
                .ok_or_eyre("missing job creation policy")?
                .try_into()?,
            labels: schedule_definition
                .labels
                .into_iter()
                .map(|label| (label.key, label.value))
                .collect(),
            time_range: schedule_definition.time_range.map(Into::into),
            metadata_json: schedule_definition.metadata_json,
        })
    }
}