~ruther/NosSmooth

ref: 1c72fa321b5e1dec1e3f9b8bf1d9c85c7f7ec983 NosSmooth/Core/NosSmooth.Core/Contracts/IContract.cs -rw-r--r-- 4.4 KiB
1c72fa32 — Rutherther Merge pull request #55 from Rutherther/feat/contracts 2 years ago
                                                                                
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
112
113
114
115
116
117
118
119
//
//  IContract.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Threading;
using System.Threading.Tasks;
using NosSmooth.Core.Contracts.Responders;
using Remora.Results;

namespace NosSmooth.Core.Contracts;

/// <summary>
/// A contract, used for executing an operation with feedback.
/// </summary>
/// <remarks>
/// Do not use this type directly, use the generic one instead.
/// </remarks>
public interface IContract
{
    /// <summary>
    /// Gets whether this contract
    /// is registered to the contractor.
    /// </summary>
    public bool IsRegistered { get; }

    /// <summary>
    /// Register this contract into contractor.
    /// </summary>
    /// <remarks>
    /// The contract will receive data from the contractor,
    /// using CheckDataAsync method. This way there may be a
    /// feedback coming back to the contract.
    /// </remarks>
    public void Register();

    /// <summary>
    /// Unregister this contract from contractor.
    /// </summary>
    public void Unregister();

    /// <summary>
    /// Update the contract with the given received data.
    /// </summary>
    /// <remarks>
    /// Called from <see cref="ContractPacketResponder"/>
    /// or similar. Used for updating the state.
    /// The contract looks for actions that trigger updates
    /// and in case it matches the <paramref name="data"/>,
    /// the state is switched.
    /// </remarks>
    /// <param name="data">The data that were received.</param>
    /// <typeparam name="TAny">The type of the data.</typeparam>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>The result that may or may not have succeeded.</returns>
    public Task<Result<ContractUpdateResponse>> Update<TAny>(TAny data, CancellationToken ct = default)
        where TAny : notnull;

    /// <summary>
    /// Executes the contract without registering it,
    /// running only the initial operation.
    /// </summary>
    /// <remarks>
    /// For example, to use skill, create a contract for
    /// using a skill and call this method.
    /// If you want to wait for response from the server,
    /// use <see cref="WaitForAsync"/> instead.
    /// That will register the contract and wait for response.
    /// </remarks>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>The result that may or may not have succeeded.</returns>
    public Task<Result> OnlyExecuteAsync(CancellationToken ct = default);
}

/// <summary>
/// A contract, used for executing an operation with feedback.
/// </summary>
/// <remarks>
/// Could be used for operations that may end successfully or fail
/// after some time, with response from the server.
///
/// Look at <see cref="ContractBuilder"/> for example usage.
/// </remarks>
/// <typeparam name="TData">The data returned by the contract in case of success.</typeparam>
/// <typeparam name="TState">Type containing the states of the contract.</typeparam>
public interface IContract<TData, TState> : IContract
    where TData : notnull
    where TState : IComparable
{
    /// <summary>
    /// Gets the current state of the contract.
    /// </summary>
    /// <remarks>
    /// To wait for any state, see <see cref="WaitForAsync"/>.
    /// </remarks>
    public TState CurrentState { get; }

    /// <summary>
    /// Gets the data of the contract obtained from packets/.
    /// </summary>
    /// <remarks>
    /// This won't be filled in case the contract
    /// is not registered.
    /// </remarks>
    public TData? Data { get; }

    /// <summary>
    /// Register to contractor and wait for the given state.
    /// Execute the initial action.
    /// </summary>
    /// <param name="state">The state to wait for.</param>
    /// <param name="unregisterAfter">Whether to unregister the contract from the contractor after the state is reached. The contract won't be updated anymore.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>The data of the contract or an error.</returns>
    /// <exception cref="InvalidOperationError">Thrown in case the given state cannot fill the data.</exception>
    public Task<Result<TData>> WaitForAsync(TState state, bool unregisterAfter = true, CancellationToken ct = default);
}
Do not follow this link