forked from Silverfish/proton-bridge
feat: implement confirmer
This commit is contained in:
1
go.mod
1
go.mod
@ -43,6 +43,7 @@ require (
|
|||||||
github.com/go-resty/resty/v2 v2.2.0
|
github.com/go-resty/resty/v2 v2.2.0
|
||||||
github.com/golang/mock v1.4.3
|
github.com/golang/mock v1.4.3
|
||||||
github.com/google/go-cmp v0.4.0
|
github.com/google/go-cmp v0.4.0
|
||||||
|
github.com/google/uuid v1.1.1
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
|
||||||
github.com/hashicorp/go-multierror v1.0.0
|
github.com/hashicorp/go-multierror v1.0.0
|
||||||
github.com/jaytaylor/html2text v0.0.0-20200220170450-61d9dc4d7195
|
github.com/jaytaylor/html2text v0.0.0-20200220170450-61d9dc4d7195
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -86,6 +86,8 @@ github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
|||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
|||||||
44
pkg/confirmer/confirmer.go
Normal file
44
pkg/confirmer/confirmer.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package confirmer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Confirmer struct {
|
||||||
|
requests map[string]*Request
|
||||||
|
locker sync.Locker
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Confirmer {
|
||||||
|
return &Confirmer{
|
||||||
|
requests: make(map[string]*Request),
|
||||||
|
locker: &sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Confirmer) NewRequest(timeout time.Duration) *Request {
|
||||||
|
c.locker.Lock()
|
||||||
|
defer c.locker.Unlock()
|
||||||
|
|
||||||
|
req := newRequest(timeout)
|
||||||
|
|
||||||
|
c.requests[req.ID()] = req
|
||||||
|
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Confirmer) SetResponse(uuid string, value bool) error {
|
||||||
|
c.locker.Lock()
|
||||||
|
defer c.locker.Unlock()
|
||||||
|
|
||||||
|
req, ok := c.requests[uuid]
|
||||||
|
if !ok {
|
||||||
|
return errors.New("no such request")
|
||||||
|
}
|
||||||
|
|
||||||
|
req.value <- value
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
50
pkg/confirmer/confirmer_test.go
Normal file
50
pkg/confirmer/confirmer_test.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package confirmer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfirmerYes(t *testing.T) {
|
||||||
|
c := New()
|
||||||
|
|
||||||
|
req := c.NewRequest(1 * time.Second)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
assert.NoError(t, c.SetResponse(req.ID(), true))
|
||||||
|
}()
|
||||||
|
|
||||||
|
res, err := req.Result()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfirmerNo(t *testing.T) {
|
||||||
|
c := New()
|
||||||
|
|
||||||
|
req := c.NewRequest(1 * time.Second)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
assert.NoError(t, c.SetResponse(req.ID(), false))
|
||||||
|
}()
|
||||||
|
|
||||||
|
res, err := req.Result()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfirmerTimeout(t *testing.T) {
|
||||||
|
c := New()
|
||||||
|
|
||||||
|
req := c.NewRequest(1 * time.Second)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
assert.NoError(t, c.SetResponse(req.ID(), true))
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err := req.Result()
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
36
pkg/confirmer/request.go
Normal file
36
pkg/confirmer/request.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package confirmer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
uuid string
|
||||||
|
value chan bool
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRequest(timeout time.Duration) *Request {
|
||||||
|
return &Request{
|
||||||
|
uuid: uuid.New().String(),
|
||||||
|
value: make(chan bool),
|
||||||
|
timeout: timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Request) ID() string {
|
||||||
|
return r.uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Request) Result() (bool, error) {
|
||||||
|
select {
|
||||||
|
case res := <-r.value:
|
||||||
|
return res, nil
|
||||||
|
|
||||||
|
case <-time.After(r.timeout):
|
||||||
|
return false, errors.New("timed out waiting for result")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user