GetNextFault returns the error message to return on next fault.
(ctx context.Context, method Method, args ...any)
| 74 | |
| 75 | // GetNextFault returns the error message to return on next fault. |
| 76 | func (s *Set) GetNextFault(ctx context.Context, method Method, args ...any) (bool, error) { |
| 77 | // Lock set for map accesses. Call counters will be updated for the fault-set, and the fault for the fault-set method |
| 78 | // will be gotten. |
| 79 | s.mu.Lock() |
| 80 | |
| 81 | s.callCounter[method]++ |
| 82 | |
| 83 | faults := s.faults[method] |
| 84 | if len(faults) == 0 { |
| 85 | s.mu.Unlock() |
| 86 | |
| 87 | return false, nil |
| 88 | } |
| 89 | |
| 90 | // Access the "next" fault. The fault at the end of the queue |
| 91 | f := faults[0] |
| 92 | // `fault` comes from `s.faults` so nested locks held at this point. |
| 93 | f.mu.Lock() |
| 94 | |
| 95 | // Count down repeat count in fault. |
| 96 | if f.repeatCount > 0 { |
| 97 | f.repeatCount-- |
| 98 | log(ctx).Debugf("will repeat %v more times the fault for %v %v", f.repeatCount, method, args) |
| 99 | } else { |
| 100 | // `repeatCount` == 0. Remove the fault if there are faults remaining in the queue ... |
| 101 | if remaining := faults[1:]; len(remaining) > 0 { |
| 102 | s.faults[method] = remaining |
| 103 | } else { |
| 104 | // ... otherwise delete the map entry for the method |
| 105 | delete(s.faults, method) |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | delay := f.sleep |
| 110 | |
| 111 | // Two locks are held, so unlock both before waiting. |
| 112 | f.mu.Unlock() |
| 113 | |
| 114 | s.mu.Unlock() |
| 115 | |
| 116 | if delay > 0 { |
| 117 | // sleep for a while |
| 118 | log(ctx).Debugf("sleeping for %v in %v %v", delay, method, args) |
| 119 | time.Sleep(delay) |
| 120 | } |
| 121 | |
| 122 | // Re-acquire fault lock to get callback functions. Callbacks will be called without lock. |
| 123 | f.mu.Lock() |
| 124 | |
| 125 | cb := f.callback |
| 126 | errCb := f.errCallback |
| 127 | |
| 128 | f.mu.Unlock() |
| 129 | |
| 130 | // No more references to `f`. Perform callbacks inline. |
| 131 | if cb != nil { |
| 132 | cb() |
| 133 | } |
no test coverage detected