~emersion/soju

3237bde9f3c567628a4f0e7f6b42ff9605fb4d12 — Simon Ser 20 days ago 07519da
Introduce deliveredStore

This hides the double-map complexity behind a dedicated type.
3 files changed, 56 insertions(+), 36 deletions(-)

M downstream.go
M upstream.go
M user.go
M downstream.go => downstream.go +15 -27
@@ 361,12 361,7 @@ func (dc *downstreamConn) ackMsgID(id string) {
		return
	}

	delivered := network.delivered.Value(entity)
	if delivered == nil {
		return
	}

	delivered[dc.clientName] = id
	network.delivered.StoreID(entity, dc.clientName, id)
}

func (dc *downstreamConn) sendPing(msgID string) {


@@ 997,24 992,27 @@ func (dc *downstreamConn) welcome() error {
			}
		})
		if firstClient {
			dc.sendNetworkBacklog(net)
			net.delivered.ForEachTarget(func(target string) {
				dc.sendTargetBacklog(net, target)
			})
		}

		// Fast-forward history to last message
		for targetCM, entry := range net.delivered.innerMap {
			delivered := entry.value.(deliveredClientMap)
			ch := net.channels.Value(targetCM)
		net.delivered.ForEachTarget(func(target string) {
			ch := net.channels.Value(target)
			if ch != nil && ch.Detached {
				continue
				return
			}

			targetCM := net.casemap(target)
			lastID, err := dc.user.msgStore.LastMsgID(net, targetCM, time.Now())
			if err != nil {
				dc.logger.Printf("failed to get last message ID: %v", err)
				continue
				return
			}
			delivered[dc.clientName] = lastID
		}

			net.delivered.StoreID(target, dc.clientName, lastID)
		})
	})

	return nil


@@ 1034,13 1032,6 @@ func (dc *downstreamConn) messageSupportsHistory(msg *irc.Message) bool {
	return false
}

func (dc *downstreamConn) sendNetworkBacklog(net *network) {
	for _, entry := range net.delivered.innerMap {
		target := entry.originalKey
		dc.sendTargetBacklog(net, target)
	}
}

func (dc *downstreamConn) sendTargetBacklog(net *network, target string) {
	if dc.caps["draft/chathistory"] || dc.user.msgStore == nil {
		return


@@ 1048,12 1039,9 @@ func (dc *downstreamConn) sendTargetBacklog(net *network, target string) {
	if ch := net.channels.Value(target); ch != nil && ch.Detached {
		return
	}
	delivered := net.delivered.Value(target)
	if delivered == nil {
		return
	}
	lastDelivered, ok := delivered[dc.clientName]
	if !ok {

	lastDelivered := net.delivered.LoadID(target, dc.clientName)
	if lastDelivered == "" {
		return
	}


M upstream.go => upstream.go +3 -6
@@ 1740,9 1740,9 @@ func (uc *upstreamConn) appendLog(entity string, msg *irc.Message) (msgID string
		return ""
	}

	delivered := uc.network.delivered.Value(entity)
	entityCM := uc.network.casemap(entity)
	if delivered == nil {

	if !uc.network.delivered.HasTarget(entity) {
		// This is the first message we receive from this target. Save the last
		// message ID in delivery receipts, so that we can send the new message
		// in the backlog if an offline client reconnects.


@@ 1752,11 1752,8 @@ func (uc *upstreamConn) appendLog(entity string, msg *irc.Message) (msgID string
			return ""
		}

		delivered = make(deliveredClientMap)
		uc.network.delivered.SetValue(entity, delivered)

		for clientName, _ := range uc.user.clients {
			delivered[clientName] = lastID
			uc.network.delivered.StoreID(entity, clientName, lastID)
		}
	}


M user.go => user.go +38 -3
@@ 57,6 57,41 @@ type eventStop struct{}

type deliveredClientMap map[string]string // client name -> msg ID

type deliveredStore struct {
	m deliveredCasemapMap
}

func newDeliveredStore() deliveredStore {
	return deliveredStore{deliveredCasemapMap{newCasemapMap(0)}}
}

func (ds deliveredStore) HasTarget(target string) bool {
	return ds.m.Value(target) != nil
}

func (ds deliveredStore) LoadID(target, clientName string) string {
	clients := ds.m.Value(target)
	if clients == nil {
		return ""
	}
	return clients[clientName]
}

func (ds deliveredStore) StoreID(target, clientName, msgID string) {
	clients := ds.m.Value(target)
	if clients == nil {
		clients = make(deliveredClientMap)
		ds.m.SetValue(target, clients)
	}
	clients[clientName] = msgID
}

func (ds deliveredStore) ForEachTarget(f func(target string)) {
	for _, entry := range ds.m.innerMap {
		f(entry.originalKey)
	}
}

type network struct {
	Network
	user    *user


@@ 64,7 99,7 @@ type network struct {

	conn      *upstreamConn
	channels  channelCasemapMap
	delivered deliveredCasemapMap
	delivered deliveredStore
	lastError error
	casemap   casemapping
}


@@ 81,7 116,7 @@ func newNetwork(user *user, record *Network, channels []Channel) *network {
		user:      user,
		stopped:   make(chan struct{}),
		channels:  m,
		delivered: deliveredCasemapMap{newCasemapMap(0)},
		delivered: newDeliveredStore(),
		casemap:   casemapRFC1459,
	}
}


@@ 253,7 288,7 @@ func (net *network) deleteChannel(name string) error {
func (net *network) updateCasemapping(newCasemap casemapping) {
	net.casemap = newCasemap
	net.channels.SetCasemapping(newCasemap)
	net.delivered.SetCasemapping(newCasemap)
	net.delivered.m.SetCasemapping(newCasemap)
	if net.conn != nil {
		net.conn.channels.SetCasemapping(newCasemap)
		for _, entry := range net.conn.channels.innerMap {