Refactorings for simplify readability (#35)

This commit is contained in:
Fedor Korotkov
2023-03-17 06:11:28 -04:00
committed by GitHub
parent 3ecf98c039
commit fb3056d3ae
21 changed files with 360 additions and 876 deletions
@@ -1,39 +0,0 @@
package concurrentmap
import (
"sync"
)
type ConcurrentMap[T any] struct {
nonConcurrentMap map[any]T
mtx sync.Mutex
}
func NewConcurrentMap[T any]() *ConcurrentMap[T] {
return &ConcurrentMap[T]{
nonConcurrentMap: map[any]T{},
}
}
func (cmap *ConcurrentMap[T]) Load(key any) (T, bool) {
cmap.mtx.Lock()
defer cmap.mtx.Unlock()
result, ok := cmap.nonConcurrentMap[key]
return result, ok
}
func (cmap *ConcurrentMap[T]) Store(id any, value T) {
cmap.mtx.Lock()
defer cmap.mtx.Unlock()
cmap.nonConcurrentMap[id] = value
}
func (cmap *ConcurrentMap[T]) Delete(key any) {
cmap.mtx.Lock()
defer cmap.mtx.Unlock()
delete(cmap.nonConcurrentMap, key)
}
-49
View File
@@ -1,49 +0,0 @@
package rendezvous
import (
"context"
"errors"
"github.com/cirruslabs/orchard/internal/controller/rendezvous/concurrentmap"
"net"
)
var ErrInvalidToken = errors.New("invalid proxy token")
type Proxy struct {
tokens *concurrentmap.ConcurrentMap[*TokenSlot]
}
type TokenSlot struct {
ctx context.Context
ch chan net.Conn
}
func NewProxy() *Proxy {
return &Proxy{
tokens: concurrentmap.NewConcurrentMap[*TokenSlot](),
}
}
func (proxy *Proxy) Request(ctx context.Context, token string) (chan net.Conn, func()) {
tokenSlot := &TokenSlot{
ctx: ctx,
ch: make(chan net.Conn),
}
proxy.tokens.Store(token, tokenSlot)
return tokenSlot.ch, func() {
proxy.tokens.Delete(token)
}
}
func (proxy *Proxy) Respond(token string, conn net.Conn) (context.Context, error) {
tokenSlot, ok := proxy.tokens.Load(token)
if !ok {
return nil, ErrInvalidToken
}
tokenSlot.ch <- conn
return tokenSlot.ctx, nil
}
@@ -1,39 +0,0 @@
package rendezvous_test
import (
"context"
"github.com/cirruslabs/orchard/internal/controller/rendezvous"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"net"
"sync"
"testing"
)
func TestProxy(t *testing.T) {
ctx := context.Background()
expectedConn, _ := net.Pipe()
proxy := rendezvous.NewProxy()
token := uuid.New().String()
connCh, cancel := proxy.Request(ctx, token)
defer cancel()
var wg sync.WaitGroup
wg.Add(1)
go func() {
_, err := proxy.Respond(token, expectedConn)
require.NoError(t, err)
wg.Done()
}()
actualConn := <-connCh
require.Equal(t, expectedConn, actualConn)
wg.Wait()
}
-57
View File
@@ -1,57 +0,0 @@
package rendezvous
import (
"context"
"errors"
"fmt"
"github.com/cirruslabs/orchard/internal/controller/rendezvous/concurrentmap"
"github.com/cirruslabs/orchard/rpc"
)
var ErrNoWorker = errors.New("no worker registered with this name")
type Watcher struct {
workers *concurrentmap.ConcurrentMap[*WorkerSlot]
}
type WorkerSlot struct {
ctx context.Context
ch chan *rpc.WatchFromController
}
func NewWatcher() *Watcher {
return &Watcher{
workers: concurrentmap.NewConcurrentMap[*WorkerSlot](),
}
}
func (watcher *Watcher) Subscribe(ctx context.Context, worker string) (chan *rpc.WatchFromController, func()) {
subCtx, cancel := context.WithCancel(ctx)
workerCh := make(chan *rpc.WatchFromController)
watcher.workers.Store(worker, &WorkerSlot{
ctx: subCtx,
ch: workerCh,
})
return workerCh, func() {
watcher.workers.Delete(worker)
cancel()
}
}
func (watcher *Watcher) Notify(ctx context.Context, topic string, msg *rpc.WatchFromController) error {
slot, ok := watcher.workers.Load(topic)
if !ok {
return fmt.Errorf("%w: %s", ErrNoWorker, topic)
}
select {
case slot.ch <- msg:
return nil
case <-slot.ctx.Done():
return slot.ctx.Err()
case <-ctx.Done():
return ctx.Err()
}
}
@@ -1,48 +0,0 @@
package rendezvous_test
import (
"context"
"fmt"
"github.com/cirruslabs/orchard/internal/controller/rendezvous"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"sync"
"testing"
"time"
)
func TestWatcher(t *testing.T) {
ctx := context.Background()
watcher := rendezvous.NewWatcher()
var topic = uuid.New().String()
msgCh, cancel := watcher.Subscribe(context.Background(), topic)
defer cancel()
var wg sync.WaitGroup
wg.Add(1)
go func() {
require.NoError(t, watcher.Notify(ctx, topic, nil))
time.Sleep(time.Second)
require.NoError(t, watcher.Notify(ctx, topic, nil))
wg.Done()
}()
fmt.Println("waiting for the message...")
<-msgCh
fmt.Println("received first message")
<-msgCh
fmt.Println("received second message")
wg.Wait()
}