loopd: move global state into server state

pull/140/head
Oliver Gugger 4 years ago
parent 55908dbec5
commit 403b4097de
No known key found for this signature in database
GPG Key ID: 8E4256593F177720

@ -16,6 +16,7 @@ import (
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/lndclient" "github.com/lightninglabs/loop/lndclient"
"github.com/lightninglabs/loop/looprpc" "github.com/lightninglabs/loop/looprpc"
"github.com/lightningnetwork/lnd/lntypes"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
@ -68,14 +69,18 @@ func daemon(config *config, lisCfg *listenerCfg) error {
return err return err
} }
swaps := make(map[lntypes.Hash]loop.SwapInfo)
for _, s := range swapsList { for _, s := range swapsList {
swaps[s.SwapHash] = *s swaps[s.SwapHash] = *s
} }
// Instantiate the loopd gRPC server. // Instantiate the loopd gRPC server.
server := swapClientServer{ server := swapClientServer{
impl: swapClient, impl: swapClient,
lnd: &lnd.LndServices, lnd: &lnd.LndServices,
swaps: swaps,
subscribers: make(map[int]chan<- interface{}),
statusChan: make(chan loop.SwapInfo),
} }
serverOpts := []grpc.ServerOption{} serverOpts := []grpc.ServerOption{}
@ -130,8 +135,6 @@ func daemon(config *config, lisCfg *listenerCfg) error {
log.Infof("REST proxy disabled") log.Infof("REST proxy disabled")
} }
statusChan := make(chan loop.SwapInfo)
mainCtx, cancel := context.WithCancel(context.Background()) mainCtx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup var wg sync.WaitGroup
@ -141,7 +144,7 @@ func daemon(config *config, lisCfg *listenerCfg) error {
defer wg.Done() defer wg.Done()
log.Infof("Starting swap client") log.Infof("Starting swap client")
err := swapClient.Run(mainCtx, statusChan) err := swapClient.Run(mainCtx, server.statusChan)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
} }
@ -159,25 +162,7 @@ func daemon(config *config, lisCfg *listenerCfg) error {
defer wg.Done() defer wg.Done()
log.Infof("Waiting for updates") log.Infof("Waiting for updates")
for { server.processStatusUpdates(mainCtx)
select {
case swap := <-statusChan:
swapsLock.Lock()
swaps[swap.SwapHash] = swap
for _, subscriber := range subscribers {
select {
case subscriber <- swap:
case <-mainCtx.Done():
return
}
}
swapsLock.Unlock()
case <-mainCtx.Done():
return
}
}
}() }()
// Start the grpc server. // Start the grpc server.

@ -7,26 +7,16 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"github.com/jessevdk/go-flags" "github.com/jessevdk/go-flags"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/lndclient" "github.com/lightninglabs/loop/lndclient"
"github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/lntypes"
) )
const ( const (
defaultConfTarget = int32(6) defaultConfTarget = int32(6)
)
var (
defaultConfigFilename = "loopd.conf" defaultConfigFilename = "loopd.conf"
swaps = make(map[lntypes.Hash]loop.SwapInfo)
subscribers = make(map[int]chan<- interface{})
nextSubscriberID int
swapsLock sync.Mutex
) )
// RPCConfig holds optional options that can be used to make the loop daemon // RPCConfig holds optional options that can be used to make the loop daemon

@ -5,8 +5,10 @@ import (
"errors" "errors"
"fmt" "fmt"
"sort" "sort"
"sync"
"time" "time"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/queue"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
@ -29,8 +31,13 @@ const (
// swapClientServer implements the grpc service exposed by loopd. // swapClientServer implements the grpc service exposed by loopd.
type swapClientServer struct { type swapClientServer struct {
impl *loop.Client impl *loop.Client
lnd *lndclient.LndServices lnd *lndclient.LndServices
swaps map[lntypes.Hash]loop.SwapInfo
subscribers map[int]chan<- interface{}
statusChan chan loop.SwapInfo
nextSubscriberID int
swapsLock sync.Mutex
} }
// LoopOut initiates an loop out swap with the given parameters. The call // LoopOut initiates an loop out swap with the given parameters. The call
@ -162,14 +169,14 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
// Add this subscriber to the global subscriber list. Also create a // Add this subscriber to the global subscriber list. Also create a
// snapshot of all pending and completed swaps within the lock, to // snapshot of all pending and completed swaps within the lock, to
// prevent subscribers from receiving duplicate updates. // prevent subscribers from receiving duplicate updates.
swapsLock.Lock() s.swapsLock.Lock()
id := nextSubscriberID id := s.nextSubscriberID
nextSubscriberID++ s.nextSubscriberID++
subscribers[id] = queue.ChanIn() s.subscribers[id] = queue.ChanIn()
var pendingSwaps, completedSwaps []loop.SwapInfo var pendingSwaps, completedSwaps []loop.SwapInfo
for _, swap := range swaps { for _, swap := range s.swaps {
if swap.State.Type() == loopdb.StateTypePending { if swap.State.Type() == loopdb.StateTypePending {
pendingSwaps = append(pendingSwaps, swap) pendingSwaps = append(pendingSwaps, swap)
} else { } else {
@ -177,13 +184,13 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
} }
} }
swapsLock.Unlock() s.swapsLock.Unlock()
defer func() { defer func() {
queue.Stop() queue.Stop()
swapsLock.Lock() s.swapsLock.Lock()
delete(subscribers, id) delete(s.subscribers, id)
swapsLock.Unlock() s.swapsLock.Unlock()
}() }()
// Sort completed swaps new to old. // Sort completed swaps new to old.
@ -383,6 +390,36 @@ func (s *swapClientServer) GetLsatTokens(ctx context.Context,
return &looprpc.TokensResponse{Tokens: rpcTokens}, nil return &looprpc.TokensResponse{Tokens: rpcTokens}, nil
} }
// processStatusUpdates reads updates on the status channel and processes them.
//
// NOTE: This must run inside a goroutine as it blocks until the main context
// shuts down.
func (s *swapClientServer) processStatusUpdates(mainCtx context.Context) {
for {
select {
// On updates, refresh the server's in-memory state and inform
// subscribers about the changes.
case swp := <-s.statusChan:
s.swapsLock.Lock()
s.swaps[swp.SwapHash] = swp
for _, subscriber := range s.subscribers {
select {
case subscriber <- swp:
case <-mainCtx.Done():
return
}
}
s.swapsLock.Unlock()
// Server is shutting down.
case <-mainCtx.Done():
return
}
}
}
// validateConfTarget ensures the given confirmation target is valid. If one // validateConfTarget ensures the given confirmation target is valid. If one
// isn't specified (0 value), then the default target is used. // isn't specified (0 value), then the default target is used.
func validateConfTarget(target, defaultTarget int32) (int32, error) { func validateConfTarget(target, defaultTarget int32) (int32, error) {

Loading…
Cancel
Save