package obelisk:types@4.0.0;

@since(version = 3.0.0)
interface time {

    @since(version = 3.0.0)
    variant duration {
        milliseconds(u64),
        seconds(u64),
        minutes(u32),
        hours(u32),
        days(u32),
    }

    /// A time and date in seconds plus nanoseconds.
    // Extracted from wasi:clocks@0.2.0 to avoid dependency on wasi:io
    @since(version = 3.0.0)
    record datetime {
        seconds: u64,
        nanoseconds: u32,
    }

    @since(version = 3.0.0)
    variant schedule-at {
        now,
        at(datetime),
        in(duration),
    }
}

@since(version = 4.0.0)
interface execution {

    @since(version = 3.0.0)
    record execution-id {
        id: string,
    }

    @since(version = 3.0.0)
    record delay-id {
        id: string,
    }

    @since(version = 3.0.0)
    record function {
        // `namespace:pkg_name/ifc_name` or `namespace:pkg_name/ifc_name@version`
        interface-name: string,
        function-name: string,
    }

    @since(version = 3.0.0)
    variant response-id {
        execution-id(execution-id),
        delay-id(delay-id),
    }

    @since(version = 3.0.0)
    record function-mismatch {
        /// Workflow requested function
        specified-function: function,
        /// What was found actually during execution. None if delay was found as next unprocessed response.
        actual-function: option<function>,
        actual-id: response-id,
    }

    /// Error that is thrown by `-await-next` extension functions.
    @since(version = 3.0.0)
    variant await-next-extension-error {
        /// All submitted requests and their responses of specified function and join set were already processed.
        all-processed,
        /// Execution response was awaited and marked as processed, but it belongs to a different function.
        /// This can happen when join set contains responses of multiple functions or delay requests.
        function-mismatch(function-mismatch),
    }

    /// Error variants that may occur when calling `-get` extension functions.
    @since(version = 3.0.0)
    variant get-extension-error {
        /// Execution is found in processed responses, but it belongs to a different function.
        /// This can happen when join set contains responses of multiple functions.
        function-mismatch(function-mismatch),
        /// Processed responses do not contain the specified execution ID.
        /// This can happen if the execution was not marked as processed (awaited), or
        /// the execution ID does not belong to the specified join set.
        not-found-in-processed-responses,
    }

    /// Error variants that may occur when calling `-invoke` extension functions.
    @since(version = 3.0.0)
    // deprecated
    variant invoke-extension-error {
        invalid-name(string),
    }

    /// Error variants that may occur when calling `-stub` extension functions.
    @since(version = 3.0.0)
    variant stub-error {
        /// Conflict can happen when a second writer attempts to stub a value, while the
        /// value is not equal to the already stubbed value.
        conflict,
    }
}


@since(version = 4.0.0)
interface join-set {
    use time.{schedule-at};
    use execution.{delay-id, response-id};

    /// Join set resouce.
    @since(version = 4.0.0)
    resource join-set {

        /// Get the join set identifier in the form of:
        /// * `o:NAME` in case of a one-off join set, where `NAME` is generally an auto-incremented index optionally followed by underscode and a supplied name,
        /// * `g:NAME` in case of a generated join set where `NAME` is generally an auto-incremented index,
        /// * `n:NAME` in case of a named join set
        @since(version = 4.0.0)
        id: func() -> string;

        /// Submit a delay request to the join set. The delay can be later polled using `join-next`.
        @since(version = 4.0.0)
        submit-delay: func(timeout: schedule-at) -> delay-id;

        /// Block the workflow execution until next response associated with the join set arrives.
        /// The response is marked as processed.
        /// Child execution result can be obtained using `-get` extension function using the
        /// returned execution ID.
        /// Return `join-next-error::all-processed` if the join set has all requests matched with responses.
        @since(version = 4.0.0)
        join-next: func() -> result<tuple<response-id, result>, join-next-error>;
    }

    /// Error variants that may occur when calling `join-next` function.
    @since(version = 4.0.0)
    variant join-next-error {
        /// All submitted requests and their responses were already processed.
        all-processed,
    }
}
