1 /**
2 * Copyright © DiamondMVC 2018
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 }