1 /**
2 * Copyright © DiamondMVC 2019
3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module diamond.data.transaction;
7 
8 /// Wrapper for transactional data management.
9 final class Transaction(T)
10 if (is(T == struct) || isScalarType!T)
11 {
12   private:
13   /// The commit delegate.
14   void delegate(Snapshot!T) _commit;
15   /// The success delegate.
16   void delegate(Snapshot!T) _success;
17   /// The failure delegate.
18   bool delegate(Snapshot!T, Throwable, size_t) _failure;
19 
20   public:
21   final:
22   /// Creates a new transactional data manager.
23   this() { }
24 
25   /**
26   * Creates a new transactional data manager.
27   * Params:
28   *   onCommit = The delegate called when committing.
29   *   onSuccess = The delegate called when a commit succeeded.
30   *   onFailure = The delegate called when a commit failed.
31   */
32   this
33   (
34     void delegate(Snapshot!T) onCommit,
35     void delegate(Snapshot!T) onSuccess,
36     bool delegate(Snapshot!T, Throwable, size_t) onFailure
37   )
38   {
39     _exec = onExec;
40     _success = onSuccess;
41     _failure = onFailure;
42   }
43 
44   @property
45   {
46     /// Sets the delegate called when comitting.
47     void commit(void delegate(Snapshot!T) onCommit)
48     {
49       _commit = onCommit;
50     }
51 
52     /// Sets the delegate called when a commit succeeded.
53     void success(void delegate(Snapshot!T) onSuccess)
54     {
55       _success = onSuccess;
56     }
57 
58     /// Sets the delegate called when a commit failed.
59     void failure(bool delegate(Snapshot!T, Throwable, size_t) onFailure)
60     {
61       _failure = onFailure;
62     }
63   }
64 
65 
66   /**
67   * Commits the transaction.
68   * Params:
69   *   snapshot = The snapshot to commit.
70   *   retries = The amount of retries a commit has had.
71   */
72   private void call(Snapshot!T snapshot, size_t retries)
73   {
74     try
75     {
76       if (_commit) _commit(snapshot);
77       if (_success) _success(snapshot);
78     }
79     catch (Throwable t)
80     {
81       if (_failure && _failure(snapshot, t, retries))
82       {
83         call(snapshot, retries + 1);
84       }
85       else
86       {
87         throw t;
88       }
89     }
90   }
91 
92   /// Operator overload for calling the transaction and committing it.
93   void opCall(Snapshot!T snapshot)
94   {
95     call(snapshot, 0);
96   }
97 }