status-go/server/timeout.go
Samuel Hawksby-Robinson 7cd7430d31
Improved Local Pairing Separation of Concerns (#3248)
* Moved all configs into config.go

* Completed build out of new config structures

* Completed SenderClient process flow

* Completed sync data Mounter and client integration

* Completed installation data Mounter and client integration

* House keeping, small refactor to match conventions.

PayloadEncryptor is passed by value and used as a pointer to the instance value and not a shared pointer.

* Reintroduced explicit Mounter field type

* Completed ReceiverClient structs and flows

* Finished BaseClient function parity with old acc

* Integrated new Clients into tests

Solved some test breaks caused by encryptors sharing pointers to their managed payloads

* Built out SenderServer and ReceiverServer structs

With all associated functions and integrated with endpoints.

* Updated tests to handle new Server types

* Added docs and additional refinement

* Renamed some files to better match the content of those files

* Added json tags to config fields that were missing explicit tags.

* fix tests relating to payload locking

* Addressing feedback from @ilmotta

* Addressed feedback from @qfrank
2023-03-23 11:44:15 +00:00

95 lines
2.4 KiB
Go

package server
import (
"sync"
"time"
)
// timeoutManager represents a discrete encapsulation of timeout functionality.
// this struct expose 3 functions:
// - SetTimeout
// - StartTimeout
// - StopTimeout
type timeoutManager struct {
// timeout number of milliseconds the timeout operation will run before executing the `terminate` func()
// 0 represents an inactive timeout
timeout uint
// exitQueue handles the cancel signal channels that circumvent timeout operations and prevent the
// execution of any `terminate` func()
exitQueue *exitQueueManager
}
// newTimeoutManager returns a fully qualified and initialised timeoutManager
func newTimeoutManager() *timeoutManager {
return &timeoutManager{
exitQueue: &exitQueueManager{queue: []chan struct{}{}},
}
}
// SetTimeout sets the value of the timeoutManager.timeout
func (t *timeoutManager) SetTimeout(milliseconds uint) {
t.timeout = milliseconds
}
// StartTimeout starts a timeout operation based on the set timeoutManager.timeout value
// the given terminate func() will be executed once the timeout duration has passed
func (t *timeoutManager) StartTimeout(terminate func()) {
if t.timeout == 0 {
return
}
t.StopTimeout()
exit := make(chan struct{}, 1)
t.exitQueue.add(exit)
go t.run(terminate, exit)
}
// StopTimeout terminates a timeout operation and exits gracefully
func (t *timeoutManager) StopTimeout() {
if t.timeout == 0 {
return
}
t.exitQueue.empty()
}
// run inits the main timeout run function that awaits for the exit command to be triggered or for the
// timeout duration to elapse and trigger the parameter terminate function.
func (t *timeoutManager) run(terminate func(), exit chan struct{}) {
select {
case <-exit:
return
case <-time.After(time.Duration(t.timeout) * time.Millisecond):
terminate()
// TODO fire signal to let UI know
// https://github.com/status-im/status-go/issues/3305
return
}
}
// exitQueueManager
type exitQueueManager struct {
queue []chan struct{}
queueLock sync.Mutex
}
// add handles new exit channels adding them to the exit queue
func (e *exitQueueManager) add(exit chan struct{}) {
e.queueLock.Lock()
defer e.queueLock.Unlock()
e.queue = append(e.queue, exit)
}
// empty sends a signal to every exit channel in the queue and then resets the queue
func (e *exitQueueManager) empty() {
e.queueLock.Lock()
defer e.queueLock.Unlock()
for i := range e.queue {
e.queue[i] <- struct{}{}
}
e.queue = []chan struct{}{}
}