From 83a4590acc905dbc508d1df559eb2eddc57a5439 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 4 Jan 2021 16:26:30 +0100 Subject: [PATCH] Add store-agnostic message ID format Allow to query the network ID and entity from the message ID regardless of the underlying store used. --- downstream.go | 4 ++-- msgstore.go | 19 +++++++++++++++++++ msgstore_fs.go | 37 ++++++++++++++++++++++--------------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/downstream.go b/downstream.go index 5b6ad3e..d4e9564 100644 --- a/downstream.go +++ b/downstream.go @@ -313,13 +313,13 @@ func (dc *downstreamConn) advanceMessageWithID(msg *irc.Message, id string) { // ackMsgID acknowledges that a message has been received. func (dc *downstreamConn) ackMsgID(id string) { - netName, entity, _, _, err := parseMsgID(id) + netID, entity, _, err := parseMsgID(id) if err != nil { dc.logger.Printf("failed to ACK message ID %q: %v", id, err) return } - network := dc.user.getNetwork(netName) + network := dc.user.getNetworkByID(netID) if network == nil { return } diff --git a/msgstore.go b/msgstore.go index 1768b25..2be4f18 100644 --- a/msgstore.go +++ b/msgstore.go @@ -1,6 +1,9 @@ package soju import ( + "fmt" + "strconv" + "strings" "time" "gopkg.in/irc.v3" @@ -18,3 +21,19 @@ type messageStore interface { LoadLatestID(network *network, entity, id string, limit int) ([]*irc.Message, error) Append(network *network, entity string, msg *irc.Message) (id string, err error) } + +func formatMsgID(netID int64, entity, extra string) string { + return fmt.Sprintf("%v %v %v", netID, entity, extra) +} + +func parseMsgID(s string) (netID int64, entity, extra string, err error) { + l := strings.SplitN(s, " ", 3) + if len(l) != 3 { + return 0, "", "", fmt.Errorf("invalid message ID %q: expected 3 fields", s) + } + netID, err = strconv.ParseInt(l[0], 10, 64) + if err != nil { + return 0, "", "", fmt.Errorf("invalid message ID %q: %v", s, err) + } + return netID, l[1], l[2], nil +} diff --git a/msgstore_fs.go b/msgstore_fs.go index 1d17cec..fdeb91c 100644 --- a/msgstore_fs.go +++ b/msgstore_fs.go @@ -36,39 +36,45 @@ func (ms *fsMessageStore) logPath(network *network, entity string, t time.Time) return filepath.Join(ms.root, escapeFilename.Replace(network.GetName()), escapeFilename.Replace(entity), filename) } -func parseMsgID(s string) (network, entity string, t time.Time, offset int64, err error) { - var year, month, day int - _, err = fmt.Sscanf(s, "%s %s %04d-%02d-%02d %d", &network, &entity, &year, &month, &day, &offset) +func parseFSMsgID(s string) (netID int64, entity string, t time.Time, offset int64, err error) { + netID, entity, extra, err := parseMsgID(s) if err != nil { - return "", "", time.Time{}, 0, fmt.Errorf("invalid message ID: %v", err) + return 0, "", time.Time{}, 0, err + } + + var year, month, day int + _, err = fmt.Sscanf(extra, "%04d-%02d-%02d %d", &year, &month, &day, &offset) + if err != nil { + return 0, "", time.Time{}, 0, fmt.Errorf("invalid message ID %q: %v", s, err) } t = time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local) - return network, entity, t, offset, nil + return netID, entity, t, offset, nil } -func formatMsgID(network, entity string, t time.Time, offset int64) string { +func formatFSMsgID(netID int64, entity string, t time.Time, offset int64) string { year, month, day := t.Date() - return fmt.Sprintf("%s %s %04d-%02d-%02d %d", network, entity, year, month, day, offset) + extra := fmt.Sprintf("%04d-%02d-%02d %d", year, month, day, offset) + return formatMsgID(netID, entity, extra) } // nextMsgID queries the message ID for the next message to be written to f. -func nextMsgID(network *network, entity string, t time.Time, f *os.File) (string, error) { +func nextFSMsgID(network *network, entity string, t time.Time, f *os.File) (string, error) { offset, err := f.Seek(0, io.SeekEnd) if err != nil { return "", err } - return formatMsgID(network.GetName(), entity, t, offset), nil + return formatFSMsgID(network.ID, entity, t, offset), nil } func (ms *fsMessageStore) LastMsgID(network *network, entity string, t time.Time) (string, error) { p := ms.logPath(network, entity, t) fi, err := os.Stat(p) if os.IsNotExist(err) { - return formatMsgID(network.GetName(), entity, t, -1), nil + return formatFSMsgID(network.ID, entity, t, -1), nil } else if err != nil { return "", err } - return formatMsgID(network.GetName(), entity, t, fi.Size()-1), nil + return formatFSMsgID(network.ID, entity, t, fi.Size()-1), nil } func (ms *fsMessageStore) Append(network *network, entity string, msg *irc.Message) (string, error) { @@ -113,7 +119,7 @@ func (ms *fsMessageStore) Append(network *network, entity string, msg *irc.Messa ms.files[entity] = f } - msgID, err := nextMsgID(network, entity, t, f) + msgID, err := nextFSMsgID(network, entity, t, f) if err != nil { return "", fmt.Errorf("failed to generate message ID: %v", err) } @@ -373,13 +379,14 @@ func (ms *fsMessageStore) LoadLatestID(network *network, entity, id string, limi var afterTime time.Time var afterOffset int64 if id != "" { - var idNet, idEntity string + var idNet int64 + var idEntity string var err error - idNet, idEntity, afterTime, afterOffset, err = parseMsgID(id) + idNet, idEntity, afterTime, afterOffset, err = parseFSMsgID(id) if err != nil { return nil, err } - if idNet != network.GetName() || idEntity != entity { + if idNet != network.ID || idEntity != entity { return nil, fmt.Errorf("cannot find message ID: message ID doesn't match network/entity") } }