Add "network delete" service command
And add all the infrastructure required to stop and delete networks. References: https://todo.sr.ht/~emersion/soju/17
This commit is contained in:
parent
1f11976e7a
commit
96039320b6
23
db.go
23
db.go
@ -215,6 +215,29 @@ func (db *DB) StoreNetwork(username string, network *Network) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DB) DeleteNetwork(id int64) error {
|
||||||
|
db.lock.Lock()
|
||||||
|
defer db.lock.Unlock()
|
||||||
|
|
||||||
|
tx, err := db.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
_, err = tx.Exec("DELETE FROM Network WHERE id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec("DELETE FROM Channel WHERE network = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DB) ListChannels(networkID int64) ([]Channel, error) {
|
func (db *DB) ListChannels(networkID int64) ([]Channel, error) {
|
||||||
db.lock.RLock()
|
db.lock.RLock()
|
||||||
defer db.lock.RUnlock()
|
defer db.lock.RUnlock()
|
||||||
|
32
service.go
32
service.go
@ -97,6 +97,11 @@ func init() {
|
|||||||
desc: "show a list of saved networks and their current status",
|
desc: "show a list of saved networks and their current status",
|
||||||
handle: handleServiceNetworkStatus,
|
handle: handleServiceNetworkStatus,
|
||||||
},
|
},
|
||||||
|
"delete": {
|
||||||
|
usage: "<name>",
|
||||||
|
desc: "delete a network",
|
||||||
|
handle: handleServiceNetworkDelete,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -143,9 +148,14 @@ func handleServiceHelp(dc *downstreamConn, params []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleServiceCreateNetwork(dc *downstreamConn, params []string) error {
|
func newFlagSet() *flag.FlagSet {
|
||||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
fs.SetOutput(ioutil.Discard)
|
fs.SetOutput(ioutil.Discard)
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleServiceCreateNetwork(dc *downstreamConn, params []string) error {
|
||||||
|
fs := newFlagSet()
|
||||||
addr := fs.String("addr", "", "")
|
addr := fs.String("addr", "", "")
|
||||||
name := fs.String("name", "", "")
|
name := fs.String("name", "", "")
|
||||||
username := fs.String("username", "", "")
|
username := fs.String("username", "", "")
|
||||||
@ -177,7 +187,7 @@ func handleServiceCreateNetwork(dc *downstreamConn, params []string) error {
|
|||||||
return fmt.Errorf("could not create network: %v", err)
|
return fmt.Errorf("could not create network: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sendServicePRIVMSG(dc, fmt.Sprintf("created network %s successfully", network.GetName()))
|
sendServicePRIVMSG(dc, fmt.Sprintf("created network %q", network.GetName()))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,3 +214,21 @@ func handleServiceNetworkStatus(dc *downstreamConn, params []string) error {
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleServiceNetworkDelete(dc *downstreamConn, params []string) error {
|
||||||
|
if len(params) != 1 {
|
||||||
|
return fmt.Errorf("expected exactly one argument")
|
||||||
|
}
|
||||||
|
|
||||||
|
net := dc.user.getNetwork(params[0])
|
||||||
|
if net == nil {
|
||||||
|
return fmt.Errorf("unknown network %q", params[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dc.user.deleteNetwork(net.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sendServicePRIVMSG(dc, fmt.Sprintf("deleted network %q", net.GetName()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
50
user.go
50
user.go
@ -37,8 +37,9 @@ type eventDownstreamDisconnected struct {
|
|||||||
|
|
||||||
type network struct {
|
type network struct {
|
||||||
Network
|
Network
|
||||||
user *user
|
user *user
|
||||||
ring *Ring
|
ring *Ring
|
||||||
|
stopped chan struct{}
|
||||||
|
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
conn *upstreamConn
|
conn *upstreamConn
|
||||||
@ -50,6 +51,7 @@ func newNetwork(user *user, record *Network) *network {
|
|||||||
Network: *record,
|
Network: *record,
|
||||||
user: user,
|
user: user,
|
||||||
ring: NewRing(user.srv.RingCap),
|
ring: NewRing(user.srv.RingCap),
|
||||||
|
stopped: make(chan struct{}),
|
||||||
history: make(map[string]uint64),
|
history: make(map[string]uint64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,6 +59,13 @@ func newNetwork(user *user, record *Network) *network {
|
|||||||
func (net *network) run() {
|
func (net *network) run() {
|
||||||
var lastTry time.Time
|
var lastTry time.Time
|
||||||
for {
|
for {
|
||||||
|
select {
|
||||||
|
case <-net.stopped:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
// This space is intentionally left blank
|
||||||
|
}
|
||||||
|
|
||||||
if dur := time.Now().Sub(lastTry); dur < retryConnectMinDelay {
|
if dur := time.Now().Sub(lastTry); dur < retryConnectMinDelay {
|
||||||
delay := retryConnectMinDelay - dur
|
delay := retryConnectMinDelay - dur
|
||||||
net.user.srv.Logger.Printf("waiting %v before trying to reconnect to %q", delay.Truncate(time.Second), net.Addr)
|
net.user.srv.Logger.Printf("waiting %v before trying to reconnect to %q", delay.Truncate(time.Second), net.Addr)
|
||||||
@ -92,6 +101,19 @@ func (net *network) upstream() *upstreamConn {
|
|||||||
return net.conn
|
return net.conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (net *network) Stop() {
|
||||||
|
select {
|
||||||
|
case <-net.stopped:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
close(net.stopped)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uc := net.upstream(); uc != nil {
|
||||||
|
uc.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type user struct {
|
type user struct {
|
||||||
User
|
User
|
||||||
srv *Server
|
srv *Server
|
||||||
@ -265,3 +287,27 @@ func (u *user) createNetwork(net *Network) (*network, error) {
|
|||||||
go network.run()
|
go network.run()
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *user) deleteNetwork(id int64) error {
|
||||||
|
for i, net := range u.networks {
|
||||||
|
if net.ID != id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := u.srv.db.DeleteNetwork(net.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.forEachDownstream(func(dc *downstreamConn) {
|
||||||
|
if dc.network != nil && dc.network == net {
|
||||||
|
dc.Close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
net.Stop()
|
||||||
|
u.networks = append(u.networks[:i], u.networks[i+1:]...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("tried deleting a non-existing network")
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user