Use firebase push IDs for messages
This commit is contained in:
parent
0413960b85
commit
2525b06c28
16 changed files with 288 additions and 91 deletions
|
@ -21,7 +21,7 @@ struct Channel {
|
|||
}
|
||||
|
||||
struct Message {
|
||||
ID uint64
|
||||
ID string
|
||||
From string
|
||||
Content string
|
||||
Time int64
|
||||
|
|
|
@ -702,6 +702,21 @@ func (d *Channel) Unmarshal(buf []byte) (uint64, error) {
|
|||
|
||||
func (d *Message) Size() (s uint64) {
|
||||
|
||||
{
|
||||
l := uint64(len(d.ID))
|
||||
|
||||
{
|
||||
|
||||
t := l
|
||||
for t >= 0x80 {
|
||||
t >>= 7
|
||||
s++
|
||||
}
|
||||
s++
|
||||
|
||||
}
|
||||
s += l
|
||||
}
|
||||
{
|
||||
l := uint64(len(d.From))
|
||||
|
||||
|
@ -732,7 +747,7 @@ func (d *Message) Size() (s uint64) {
|
|||
}
|
||||
s += l
|
||||
}
|
||||
s += 16
|
||||
s += 8
|
||||
return
|
||||
}
|
||||
func (d *Message) Marshal(buf []byte) ([]byte, error) {
|
||||
|
@ -747,9 +762,23 @@ func (d *Message) Marshal(buf []byte) ([]byte, error) {
|
|||
i := uint64(0)
|
||||
|
||||
{
|
||||
l := uint64(len(d.ID))
|
||||
|
||||
*(*uint64)(unsafe.Pointer(&buf[0])) = d.ID
|
||||
{
|
||||
|
||||
t := uint64(l)
|
||||
|
||||
for t >= 0x80 {
|
||||
buf[i+0] = byte(t) | 0x80
|
||||
t >>= 7
|
||||
i++
|
||||
}
|
||||
buf[i+0] = byte(t)
|
||||
i++
|
||||
|
||||
}
|
||||
copy(buf[i+0:], d.ID)
|
||||
i += l
|
||||
}
|
||||
{
|
||||
l := uint64(len(d.From))
|
||||
|
@ -759,15 +788,15 @@ func (d *Message) Marshal(buf []byte) ([]byte, error) {
|
|||
t := uint64(l)
|
||||
|
||||
for t >= 0x80 {
|
||||
buf[i+8] = byte(t) | 0x80
|
||||
buf[i+0] = byte(t) | 0x80
|
||||
t >>= 7
|
||||
i++
|
||||
}
|
||||
buf[i+8] = byte(t)
|
||||
buf[i+0] = byte(t)
|
||||
i++
|
||||
|
||||
}
|
||||
copy(buf[i+8:], d.From)
|
||||
copy(buf[i+0:], d.From)
|
||||
i += l
|
||||
}
|
||||
{
|
||||
|
@ -778,43 +807,38 @@ func (d *Message) Marshal(buf []byte) ([]byte, error) {
|
|||
t := uint64(l)
|
||||
|
||||
for t >= 0x80 {
|
||||
buf[i+8] = byte(t) | 0x80
|
||||
buf[i+0] = byte(t) | 0x80
|
||||
t >>= 7
|
||||
i++
|
||||
}
|
||||
buf[i+8] = byte(t)
|
||||
buf[i+0] = byte(t)
|
||||
i++
|
||||
|
||||
}
|
||||
copy(buf[i+8:], d.Content)
|
||||
copy(buf[i+0:], d.Content)
|
||||
i += l
|
||||
}
|
||||
{
|
||||
|
||||
*(*int64)(unsafe.Pointer(&buf[i+8])) = d.Time
|
||||
*(*int64)(unsafe.Pointer(&buf[i+0])) = d.Time
|
||||
|
||||
}
|
||||
return buf[:i+16], nil
|
||||
return buf[:i+8], nil
|
||||
}
|
||||
|
||||
func (d *Message) Unmarshal(buf []byte) (uint64, error) {
|
||||
i := uint64(0)
|
||||
|
||||
{
|
||||
|
||||
d.ID = *(*uint64)(unsafe.Pointer(&buf[i+0]))
|
||||
|
||||
}
|
||||
{
|
||||
l := uint64(0)
|
||||
|
||||
{
|
||||
|
||||
bs := uint8(7)
|
||||
t := uint64(buf[i+8] & 0x7F)
|
||||
for buf[i+8]&0x80 == 0x80 {
|
||||
t := uint64(buf[i+0] & 0x7F)
|
||||
for buf[i+0]&0x80 == 0x80 {
|
||||
i++
|
||||
t |= uint64(buf[i+8]&0x7F) << bs
|
||||
t |= uint64(buf[i+0]&0x7F) << bs
|
||||
bs += 7
|
||||
}
|
||||
i++
|
||||
|
@ -822,7 +846,7 @@ func (d *Message) Unmarshal(buf []byte) (uint64, error) {
|
|||
l = t
|
||||
|
||||
}
|
||||
d.From = string(buf[i+8 : i+8+l])
|
||||
d.ID = string(buf[i+0 : i+0+l])
|
||||
i += l
|
||||
}
|
||||
{
|
||||
|
@ -831,10 +855,10 @@ func (d *Message) Unmarshal(buf []byte) (uint64, error) {
|
|||
{
|
||||
|
||||
bs := uint8(7)
|
||||
t := uint64(buf[i+8] & 0x7F)
|
||||
for buf[i+8]&0x80 == 0x80 {
|
||||
t := uint64(buf[i+0] & 0x7F)
|
||||
for buf[i+0]&0x80 == 0x80 {
|
||||
i++
|
||||
t |= uint64(buf[i+8]&0x7F) << bs
|
||||
t |= uint64(buf[i+0]&0x7F) << bs
|
||||
bs += 7
|
||||
}
|
||||
i++
|
||||
|
@ -842,13 +866,33 @@ func (d *Message) Unmarshal(buf []byte) (uint64, error) {
|
|||
l = t
|
||||
|
||||
}
|
||||
d.Content = string(buf[i+8 : i+8+l])
|
||||
d.From = string(buf[i+0 : i+0+l])
|
||||
i += l
|
||||
}
|
||||
{
|
||||
l := uint64(0)
|
||||
|
||||
{
|
||||
|
||||
bs := uint8(7)
|
||||
t := uint64(buf[i+0] & 0x7F)
|
||||
for buf[i+0]&0x80 == 0x80 {
|
||||
i++
|
||||
t |= uint64(buf[i+0]&0x7F) << bs
|
||||
bs += 7
|
||||
}
|
||||
i++
|
||||
|
||||
l = t
|
||||
|
||||
}
|
||||
d.Content = string(buf[i+0 : i+0+l])
|
||||
i += l
|
||||
}
|
||||
{
|
||||
|
||||
d.Time = *(*int64)(unsafe.Pointer(&buf[i+8]))
|
||||
d.Time = *(*int64)(unsafe.Pointer(&buf[i+0]))
|
||||
|
||||
}
|
||||
return i + 16, nil
|
||||
return i + 8, nil
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package storage
|
|||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/blevesearch/bleve"
|
||||
|
@ -12,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
type Message struct {
|
||||
ID uint64 `json:"id" bleve:"-"`
|
||||
ID string `json:"id" bleve:"-"`
|
||||
Server string `json:"-" bleve:"server"`
|
||||
From string `json:"from" bleve:"-"`
|
||||
To string `json:"-" bleve:"to"`
|
||||
|
@ -24,37 +22,35 @@ func (m Message) Type() string {
|
|||
return "message"
|
||||
}
|
||||
|
||||
func (u *User) LogMessage(server, from, to, content string) error {
|
||||
func (u *User) LogMessage(id, server, from, to, content string) error {
|
||||
message := Message{
|
||||
ID: id,
|
||||
Server: server,
|
||||
From: from,
|
||||
To: to,
|
||||
Content: content,
|
||||
Time: time.Now().Unix(),
|
||||
}
|
||||
bucketKey := server + ":" + to
|
||||
|
||||
err := u.messageLog.Batch(func(tx *bolt.Tx) error {
|
||||
b, err := tx.Bucket(bucketMessages).CreateBucketIfNotExists([]byte(bucketKey))
|
||||
b, err := tx.Bucket(bucketMessages).CreateBucketIfNotExists([]byte(server + ":" + to))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message.ID, _ = b.NextSequence()
|
||||
|
||||
data, err := message.Marshal(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Put(idToBytes(message.ID), data)
|
||||
return b.Put([]byte(id), data)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return u.messageIndex.Index(bucketKey+":"+strconv.FormatUint(message.ID, 10), message)
|
||||
return u.messageIndex.Index(id, message)
|
||||
}
|
||||
|
||||
func (u *User) GetLastMessages(server, channel string, count int) ([]Message, error) {
|
||||
|
@ -85,7 +81,7 @@ func (u *User) GetLastMessages(server, channel string, count int) ([]Message, er
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (u *User) GetMessages(server, channel string, count int, fromID uint64) ([]Message, error) {
|
||||
func (u *User) GetMessages(server, channel string, count int, fromID string) ([]Message, error) {
|
||||
messages := make([]Message, count)
|
||||
|
||||
u.messageLog.View(func(tx *bolt.Tx) error {
|
||||
|
@ -95,7 +91,7 @@ func (u *User) GetMessages(server, channel string, count int, fromID uint64) ([]
|
|||
}
|
||||
|
||||
c := b.Cursor()
|
||||
c.Seek(idToBytes(fromID))
|
||||
c.Seek([]byte(fromID))
|
||||
|
||||
for k, v := c.Prev(); count > 0 && k != nil; k, v = c.Prev() {
|
||||
count--
|
||||
|
@ -134,15 +130,11 @@ func (u *User) SearchMessages(server, channel, q string) ([]Message, error) {
|
|||
|
||||
messages := []Message{}
|
||||
u.messageLog.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketMessages)
|
||||
b := tx.Bucket(bucketMessages).Bucket([]byte(server + ":" + channel))
|
||||
|
||||
for _, hit := range searchResults.Hits {
|
||||
idx := strings.LastIndex(hit.ID, ":")
|
||||
bc := b.Bucket([]byte(hit.ID[:idx]))
|
||||
id, _ := strconv.ParseUint(hit.ID[idx+1:], 10, 64)
|
||||
|
||||
message := Message{}
|
||||
message.Unmarshal(bc.Get(idToBytes(id)))
|
||||
message.Unmarshal(b.Get([]byte(hit.ID)))
|
||||
messages = append(messages, message)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/kjk/betterguid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -87,7 +88,7 @@ func TestMessages(t *testing.T) {
|
|||
user, err := NewUser()
|
||||
assert.Nil(t, err)
|
||||
|
||||
messages, err := user.GetMessages("irc.freenode.net", "#go-nuts", 10, 6)
|
||||
messages, err := user.GetMessages("irc.freenode.net", "#go-nuts", 10, "6")
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, messages, 0)
|
||||
|
||||
|
@ -99,28 +100,31 @@ func TestMessages(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.Len(t, messages, 0)
|
||||
|
||||
ids := []string{}
|
||||
for i := 0; i < 5; i++ {
|
||||
err = user.LogMessage("irc.freenode.net", "nick", "#go-nuts", "message"+strconv.Itoa(i))
|
||||
id := betterguid.New()
|
||||
ids = append(ids, id)
|
||||
err = user.LogMessage(id, "irc.freenode.net", "nick", "#go-nuts", "message"+strconv.Itoa(i))
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
messages, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, 6)
|
||||
messages, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, ids[4])
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message3", messages[3].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, messages, 4)
|
||||
|
||||
messages, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, betterguid.New())
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message4", messages[4].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, messages, 5)
|
||||
|
||||
messages, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, 100)
|
||||
messages, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, ids[2])
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message4", messages[4].Content)
|
||||
assert.Equal(t, "message1", messages[1].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, messages, 5)
|
||||
|
||||
messages, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, 4)
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message2", messages[2].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, messages, 3)
|
||||
assert.Len(t, messages, 2)
|
||||
|
||||
messages, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 10)
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue