mirror of https://github.com/status-im/go-waku.git
refactor: use envelopes in the store
Also do some linting and add documentation for some functions
This commit is contained in:
parent
0df1a21dba
commit
c98769b7f2
|
@ -5,6 +5,8 @@ import (
|
|||
"net"
|
||||
)
|
||||
|
||||
// GetResolver returns a *net.Resolver object using a custom nameserver, or
|
||||
// the default system resolver if no nameserver is specified
|
||||
func GetResolver(ctx context.Context, nameserver string) *net.Resolver {
|
||||
if nameserver == "" {
|
||||
return net.DefaultResolver
|
||||
|
|
|
@ -45,7 +45,7 @@ func TestConnectionStatusChanges(t *testing.T) {
|
|||
node1, err := New(ctx,
|
||||
WithHostAddress([]*net.TCPAddr{hostAddr1}),
|
||||
WithWakuRelay(),
|
||||
WithConnStatusChan(connStatusChan),
|
||||
WithConnectionStatusChannel(connStatusChan),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
err = node1.Start()
|
||||
|
|
|
@ -48,7 +48,7 @@ type KeyInfo struct {
|
|||
|
||||
}
|
||||
|
||||
// Encodes a payload depending on the version parameter.
|
||||
// Encode encodes a payload depending on the version parameter.
|
||||
// 0 for raw unencrypted data, and 1 for using WakuV1 encoding.
|
||||
func (payload Payload) Encode(version uint32) ([]byte, error) {
|
||||
switch version {
|
||||
|
@ -105,7 +105,7 @@ func EncodeWakuMessage(message *pb.WakuMessage, keyInfo *KeyInfo) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Decodes a WakuMessage depending on the version parameter.
|
||||
// DecodePayload decodes a WakuMessage depending on the version parameter.
|
||||
// 0 for raw unencrypted data, and 1 for using WakuV1 decoding
|
||||
func DecodePayload(message *pb.WakuMessage, keyInfo *KeyInfo) (*DecodedPayload, error) {
|
||||
switch message.Version {
|
||||
|
|
|
@ -112,8 +112,8 @@ func New(ctx context.Context, opts ...WakuNodeOption) (*WakuNode, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if params.connStatusChan != nil {
|
||||
w.connStatusChan = params.connStatusChan
|
||||
if params.connStatusC != nil {
|
||||
w.connStatusChan = params.connStatusC
|
||||
}
|
||||
|
||||
w.connectionNotif = NewConnectionNotifier(ctx, host)
|
||||
|
@ -346,8 +346,8 @@ func (w *WakuNode) AddPeer(address ma.Multiaddr, protocolID p2pproto.ID) (*peer.
|
|||
|
||||
// Wrapper around WakuFilter.Subscribe
|
||||
// that adds a Filter object to node.filters
|
||||
func (node *WakuNode) SubscribeFilter(ctx context.Context, f filter.ContentFilter) (filterID string, ch chan *protocol.Envelope, err error) {
|
||||
if node.filter == nil {
|
||||
func (w *WakuNode) SubscribeFilter(ctx context.Context, f filter.ContentFilter) (filterID string, ch chan *protocol.Envelope, err error) {
|
||||
if w.filter == nil {
|
||||
err = errors.New("WakuFilter is not set")
|
||||
return
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ func (node *WakuNode) SubscribeFilter(ctx context.Context, f filter.ContentFilte
|
|||
|
||||
// Registers for messages that match a specific filter. Triggers the handler whenever a message is received.
|
||||
// ContentFilterChan takes MessagePush structs
|
||||
subs, err := node.filter.Subscribe(ctx, f)
|
||||
subs, err := w.filter.Subscribe(ctx, f)
|
||||
if err != nil || subs.RequestID == "" {
|
||||
// Failed to subscribe
|
||||
log.Error("remote subscription to filter failed", err)
|
||||
|
@ -367,7 +367,7 @@ func (node *WakuNode) SubscribeFilter(ctx context.Context, f filter.ContentFilte
|
|||
ch = make(chan *protocol.Envelope, 1024) // To avoid blocking
|
||||
|
||||
// Register handler for filter, whether remote subscription succeeded or not
|
||||
node.filters[subs.RequestID] = filter.Filter{
|
||||
w.filters[subs.RequestID] = filter.Filter{
|
||||
PeerID: subs.Peer,
|
||||
Topic: f.Topic,
|
||||
ContentFilters: f.ContentTopics,
|
||||
|
@ -379,11 +379,11 @@ func (node *WakuNode) SubscribeFilter(ctx context.Context, f filter.ContentFilte
|
|||
|
||||
// UnsubscribeFilterByID removes a subscription to a filter node completely
|
||||
// using the filterID returned when the subscription was created
|
||||
func (node *WakuNode) UnsubscribeFilterByID(ctx context.Context, filterID string) error {
|
||||
func (w *WakuNode) UnsubscribeFilterByID(ctx context.Context, filterID string) error {
|
||||
|
||||
var f filter.Filter
|
||||
var ok bool
|
||||
if f, ok = node.filters[filterID]; !ok {
|
||||
if f, ok = w.filters[filterID]; !ok {
|
||||
return errors.New("filter not found")
|
||||
}
|
||||
|
||||
|
@ -392,29 +392,29 @@ func (node *WakuNode) UnsubscribeFilterByID(ctx context.Context, filterID string
|
|||
ContentTopics: f.ContentFilters,
|
||||
}
|
||||
|
||||
err := node.filter.Unsubscribe(ctx, cf, f.PeerID)
|
||||
err := w.filter.Unsubscribe(ctx, cf, f.PeerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
close(f.Chan)
|
||||
delete(node.filters, filterID)
|
||||
delete(w.filters, filterID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unsubscribe filter removes content topics from a filter subscription. If all
|
||||
// the contentTopics are removed the subscription is dropped completely
|
||||
func (node *WakuNode) UnsubscribeFilter(ctx context.Context, cf filter.ContentFilter) error {
|
||||
func (w *WakuNode) UnsubscribeFilter(ctx context.Context, cf filter.ContentFilter) error {
|
||||
// Remove local filter
|
||||
var idsToRemove []string
|
||||
for id, f := range node.filters {
|
||||
for id, f := range w.filters {
|
||||
if f.Topic != cf.Topic {
|
||||
continue
|
||||
}
|
||||
|
||||
// Send message to full node in order to unsubscribe
|
||||
err := node.filter.Unsubscribe(ctx, cf, f.PeerID)
|
||||
err := w.filter.Unsubscribe(ctx, cf, f.PeerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -439,10 +439,10 @@ func (node *WakuNode) UnsubscribeFilter(ctx context.Context, cf filter.ContentFi
|
|||
}
|
||||
|
||||
for _, rId := range idsToRemove {
|
||||
for id := range node.filters {
|
||||
for id := range w.filters {
|
||||
if id == rId {
|
||||
close(node.filters[id].Chan)
|
||||
delete(node.filters, id)
|
||||
close(w.filters[id].Chan)
|
||||
delete(w.filters, id)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,15 +47,17 @@ type WakuNodeParameters struct {
|
|||
|
||||
enableLightPush bool
|
||||
|
||||
connStatusChan chan ConnStatus
|
||||
connStatusC chan ConnStatus
|
||||
}
|
||||
|
||||
type WakuNodeOption func(*WakuNodeParameters) error
|
||||
|
||||
// MultiAddresses return the list of multiaddresses configured in the node
|
||||
func (w WakuNodeParameters) MultiAddresses() []ma.Multiaddr {
|
||||
return w.multiAddr
|
||||
}
|
||||
|
||||
// Identity returns a libp2p option containing the identity used by the node
|
||||
func (w WakuNodeParameters) Identity() config.Option {
|
||||
return libp2p.Identity(*w.privKey)
|
||||
}
|
||||
|
@ -134,6 +136,8 @@ func WithWakuRelay(opts ...pubsub.Option) WakuNodeOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithRendezvous is a WakuOption used to enable go-waku-rendezvous discovery.
|
||||
// It accepts an optional list of DiscoveryOpt options
|
||||
func WithRendezvous(discoverOpts ...pubsub.DiscoverOpt) WakuNodeOption {
|
||||
return func(params *WakuNodeParameters) error {
|
||||
params.enableRendezvous = true
|
||||
|
@ -142,6 +146,8 @@ func WithRendezvous(discoverOpts ...pubsub.DiscoverOpt) WakuNodeOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithRendezvousServer is a WakuOption used to set the node as a rendezvous
|
||||
// point, using an specific storage for the peer information
|
||||
func WithRendezvousServer(storage rendezvous.Storage) WakuNodeOption {
|
||||
return func(params *WakuNodeParameters) error {
|
||||
params.enableRendezvousServer = true
|
||||
|
@ -188,6 +194,8 @@ func WithLightPush() WakuNodeOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithKeepAlive is a WakuNodeOption used to set the interval of time when
|
||||
// each peer will be ping to keep the TCP connection alive
|
||||
func WithKeepAlive(t time.Duration) WakuNodeOption {
|
||||
return func(params *WakuNodeParameters) error {
|
||||
params.keepAliveInterval = t
|
||||
|
@ -195,9 +203,12 @@ func WithKeepAlive(t time.Duration) WakuNodeOption {
|
|||
}
|
||||
}
|
||||
|
||||
func WithConnStatusChan(connStatusChan chan ConnStatus) WakuNodeOption {
|
||||
// WithConnectionStatusChannel is a WakuNodeOption used to set a channel where the
|
||||
// connection status changes will be pushed to. It's useful to identify when peer
|
||||
// connections and disconnections occur
|
||||
func WithConnectionStatusChannel(connStatus chan ConnStatus) WakuNodeOption {
|
||||
return func(params *WakuNodeParameters) error {
|
||||
params.connStatusChan = connStatusChan
|
||||
params.connStatusC = connStatus
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ package protocol
|
|||
|
||||
import "github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||
|
||||
// Envelope contains information about the pubsub topic of a WakuMessage
|
||||
// and a hash used to identify a message based on the bytes of a WakuMessage
|
||||
// protobuffer
|
||||
type Envelope struct {
|
||||
msg *pb.WakuMessage
|
||||
pubsubTopic string
|
||||
|
|
|
@ -220,11 +220,11 @@ func (wakuLP *WakuLightPush) request(ctx context.Context, req *pb.PushRequest, o
|
|||
return pushResponseRPC.Response, nil
|
||||
}
|
||||
|
||||
func (w *WakuLightPush) Stop() {
|
||||
w.h.RemoveStreamHandler(LightPushID_v20beta1)
|
||||
func (wakuLP *WakuLightPush) Stop() {
|
||||
wakuLP.h.RemoveStreamHandler(LightPushID_v20beta1)
|
||||
}
|
||||
|
||||
func (w *WakuLightPush) Publish(ctx context.Context, message *pb.WakuMessage, topic *relay.Topic, opts ...LightPushOption) ([]byte, error) {
|
||||
func (wakuLP *WakuLightPush) Publish(ctx context.Context, message *pb.WakuMessage, topic *relay.Topic, opts ...LightPushOption) ([]byte, error) {
|
||||
if message == nil {
|
||||
return nil, errors.New("message can't be null")
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ func (w *WakuLightPush) Publish(ctx context.Context, message *pb.WakuMessage, to
|
|||
req.Message = message
|
||||
req.PubsubTopic = string(relay.GetTopic(topic))
|
||||
|
||||
response, err := w.request(ctx, req, opts...)
|
||||
response, err := wakuLP.request(ctx, req, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -9,25 +9,26 @@ import (
|
|||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/libp2p/go-libp2p-core/peerstore"
|
||||
"github.com/status-im/go-waku/tests"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFindLastSeenMessage(t *testing.T) {
|
||||
msg1 := tests.CreateWakuMessage("1", 1)
|
||||
msg2 := tests.CreateWakuMessage("2", 2)
|
||||
msg3 := tests.CreateWakuMessage("3", 3)
|
||||
msg4 := tests.CreateWakuMessage("4", 4)
|
||||
msg5 := tests.CreateWakuMessage("5", 5)
|
||||
msg1 := protocol.NewEnvelope(tests.CreateWakuMessage("1", 1), "test")
|
||||
msg2 := protocol.NewEnvelope(tests.CreateWakuMessage("2", 2), "test")
|
||||
msg3 := protocol.NewEnvelope(tests.CreateWakuMessage("3", 3), "test")
|
||||
msg4 := protocol.NewEnvelope(tests.CreateWakuMessage("4", 4), "test")
|
||||
msg5 := protocol.NewEnvelope(tests.CreateWakuMessage("5", 5), "test")
|
||||
|
||||
s := NewWakuStore(nil)
|
||||
s.storeMessage("test", msg1)
|
||||
s.storeMessage("test", msg3)
|
||||
s.storeMessage("test", msg5)
|
||||
s.storeMessage("test", msg2)
|
||||
s.storeMessage("test", msg4)
|
||||
s.storeMessage(msg1)
|
||||
s.storeMessage(msg3)
|
||||
s.storeMessage(msg5)
|
||||
s.storeMessage(msg2)
|
||||
s.storeMessage(msg4)
|
||||
|
||||
require.Equal(t, msg5.Timestamp, s.findLastSeen())
|
||||
require.Equal(t, msg5.Message().Timestamp, s.findLastSeen())
|
||||
}
|
||||
|
||||
func TestResume(t *testing.T) {
|
||||
|
@ -47,8 +48,8 @@ func TestResume(t *testing.T) {
|
|||
contentTopic = "2"
|
||||
}
|
||||
|
||||
msg := tests.CreateWakuMessage(contentTopic, float64(time.Duration(i)*time.Second))
|
||||
s1.storeMessage("test", msg)
|
||||
msg := protocol.NewEnvelope(tests.CreateWakuMessage(contentTopic, float64(time.Duration(i)*time.Second)), "test")
|
||||
s1.storeMessage(msg)
|
||||
}
|
||||
|
||||
host2, err := libp2p.New(ctx, libp2p.DefaultTransports, libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
|
||||
|
@ -92,7 +93,7 @@ func TestResumeWithListOfPeers(t *testing.T) {
|
|||
|
||||
msg0 := &pb.WakuMessage{Payload: []byte{1, 2, 3}, ContentTopic: "2", Version: 0, Timestamp: float64(0 * time.Second)}
|
||||
|
||||
s1.storeMessage("test", msg0)
|
||||
s1.storeMessage(protocol.NewEnvelope(msg0, "test"))
|
||||
|
||||
host2, err := libp2p.New(ctx, libp2p.DefaultTransports, libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
|
||||
require.NoError(t, err)
|
||||
|
@ -125,7 +126,7 @@ func TestResumeWithoutSpecifyingPeer(t *testing.T) {
|
|||
|
||||
msg0 := &pb.WakuMessage{Payload: []byte{1, 2, 3}, ContentTopic: "2", Version: 0, Timestamp: float64(0 * time.Second)}
|
||||
|
||||
s1.storeMessage("test", msg0)
|
||||
s1.storeMessage(protocol.NewEnvelope(msg0, "test"))
|
||||
|
||||
host2, err := libp2p.New(ctx, libp2p.DefaultTransports, libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -3,7 +3,6 @@ package store
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -27,8 +26,11 @@ import (
|
|||
|
||||
var log = logging.Logger("wakustore")
|
||||
|
||||
// StoreID_v20beta3 is the current Waku Store protocol identifier
|
||||
const StoreID_v20beta3 = libp2pProtocol.ID("/vac/waku/store/2.0.0-beta3")
|
||||
const MaxPageSize = 100 // Maximum number of waku messages in each page
|
||||
|
||||
// MaxPageSize is the maximum number of waku messages to return per page
|
||||
const MaxPageSize = 100
|
||||
|
||||
var (
|
||||
ErrNoPeersAvailable = errors.New("no suitable remote peers")
|
||||
|
@ -138,11 +140,11 @@ func paginateWithoutIndex(list []IndexedWakuMessage, pinfo *pb.PagingInfo) (resM
|
|||
return
|
||||
}
|
||||
|
||||
func (w *WakuStore) FindMessages(query *pb.HistoryQuery) *pb.HistoryResponse {
|
||||
func (store *WakuStore) FindMessages(query *pb.HistoryQuery) *pb.HistoryResponse {
|
||||
result := new(pb.HistoryResponse)
|
||||
// data holds IndexedWakuMessage whose topics match the query
|
||||
var data []IndexedWakuMessage
|
||||
for _, indexedMsg := range w.messages {
|
||||
for _, indexedMsg := range store.messages {
|
||||
// temporal filtering
|
||||
// check whether the history query contains a time filter
|
||||
if query.StartTime != 0 && query.EndTime != 0 {
|
||||
|
@ -195,6 +197,7 @@ type Query struct {
|
|||
EndTime float64
|
||||
}
|
||||
|
||||
// Result represents a valid response from a store node
|
||||
type Result struct {
|
||||
Messages []*pb.WakuMessage
|
||||
|
||||
|
@ -235,6 +238,7 @@ type WakuStore struct {
|
|||
h host.Host
|
||||
}
|
||||
|
||||
// NewWakuStore creates a WakuStore using an specific MessageProvider for storing the messages
|
||||
func NewWakuStore(p MessageProvider) *WakuStore {
|
||||
wakuStore := new(WakuStore)
|
||||
wakuStore.msgProvider = p
|
||||
|
@ -243,10 +247,12 @@ func NewWakuStore(p MessageProvider) *WakuStore {
|
|||
return wakuStore
|
||||
}
|
||||
|
||||
func (store *WakuStore) SetMsgProvider(p MessageProvider) {
|
||||
// SetMessageProvider allows switching the message provider used with a WakuStore
|
||||
func (store *WakuStore) SetMessageProvider(p MessageProvider) {
|
||||
store.msgProvider = p
|
||||
}
|
||||
|
||||
// Start initializes the WakuStore by enabling the protocol and fetching records from a message provider
|
||||
func (store *WakuStore) Start(ctx context.Context, h host.Host) {
|
||||
if store.started {
|
||||
return
|
||||
|
@ -307,8 +313,8 @@ func (store *WakuStore) storeMessageWithIndex(pubsubTopic string, idx *pb.Index,
|
|||
store.messages = append(store.messages, IndexedWakuMessage{msg: msg, index: idx, pubsubTopic: pubsubTopic})
|
||||
}
|
||||
|
||||
func (store *WakuStore) storeMessage(pubSubTopic string, msg *pb.WakuMessage) {
|
||||
index, err := computeIndex(msg)
|
||||
func (store *WakuStore) storeMessage(env *protocol.Envelope) {
|
||||
index, err := computeIndex(env)
|
||||
if err != nil {
|
||||
log.Error("could not calculate message index", err)
|
||||
return
|
||||
|
@ -317,14 +323,14 @@ func (store *WakuStore) storeMessage(pubSubTopic string, msg *pb.WakuMessage) {
|
|||
store.messagesMutex.Lock()
|
||||
defer store.messagesMutex.Unlock()
|
||||
|
||||
store.storeMessageWithIndex(pubSubTopic, index, msg)
|
||||
store.storeMessageWithIndex(env.PubsubTopic(), index, env.Message())
|
||||
|
||||
if store.msgProvider == nil {
|
||||
metrics.RecordMessage(store.ctx, "stored", len(store.messages))
|
||||
return
|
||||
}
|
||||
|
||||
err = store.msgProvider.Put(index, pubSubTopic, msg) // Should the index be stored?
|
||||
err = store.msgProvider.Put(index, env.PubsubTopic(), env.Message()) // Should the index be stored?
|
||||
|
||||
if err != nil {
|
||||
log.Error("could not store message", err)
|
||||
|
@ -337,7 +343,7 @@ func (store *WakuStore) storeMessage(pubSubTopic string, msg *pb.WakuMessage) {
|
|||
|
||||
func (store *WakuStore) storeIncomingMessages(ctx context.Context) {
|
||||
for envelope := range store.MsgC {
|
||||
store.storeMessage(envelope.PubsubTopic(), envelope.Message())
|
||||
store.storeMessage(envelope)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,16 +377,11 @@ func (store *WakuStore) onRequest(s network.Stream) {
|
|||
}
|
||||
}
|
||||
|
||||
func computeIndex(msg *pb.WakuMessage) (*pb.Index, error) {
|
||||
data, err := msg.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digest := sha256.Sum256(data)
|
||||
func computeIndex(env *protocol.Envelope) (*pb.Index, error) {
|
||||
return &pb.Index{
|
||||
Digest: digest[:],
|
||||
Digest: env.Hash(),
|
||||
ReceiverTime: utils.GetUnixEpoch(),
|
||||
SenderTime: msg.Timestamp,
|
||||
SenderTime: env.Message().Timestamp,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -436,12 +437,15 @@ type HistoryRequestParameters struct {
|
|||
|
||||
type HistoryRequestOption func(*HistoryRequestParameters)
|
||||
|
||||
// WithPeer is an option used to specify the peerID to request the message history
|
||||
func WithPeer(p peer.ID) HistoryRequestOption {
|
||||
return func(params *HistoryRequestParameters) {
|
||||
params.selectedPeer = p
|
||||
}
|
||||
}
|
||||
|
||||
// WithAutomaticPeerSelection is an option used to randomly select a peer from the store
|
||||
// to request the message history
|
||||
func WithAutomaticPeerSelection() HistoryRequestOption {
|
||||
return func(params *HistoryRequestParameters) {
|
||||
p, err := utils.SelectPeer(params.s.h, string(StoreID_v20beta3))
|
||||
|
@ -471,6 +475,7 @@ func WithCursor(c *pb.Index) HistoryRequestOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithPaging is an option used to specify the order and maximum number of records to return
|
||||
func WithPaging(asc bool, pageSize uint64) HistoryRequestOption {
|
||||
return func(params *HistoryRequestParameters) {
|
||||
params.asc = asc
|
||||
|
@ -478,11 +483,12 @@ func WithPaging(asc bool, pageSize uint64) HistoryRequestOption {
|
|||
}
|
||||
}
|
||||
|
||||
// Default options to be used when querying a store node for results
|
||||
func DefaultOptions() []HistoryRequestOption {
|
||||
return []HistoryRequestOption{
|
||||
WithAutomaticRequestId(),
|
||||
WithAutomaticPeerSelection(),
|
||||
WithPaging(true, 0),
|
||||
WithPaging(true, MaxPageSize),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,6 +589,10 @@ func (store *WakuStore) Query(ctx context.Context, query Query, opts ...HistoryR
|
|||
}, nil
|
||||
}
|
||||
|
||||
// Next is used with to retrieve the next page of rows from a query response.
|
||||
// If no more records are found, the result will not contain any messages.
|
||||
// This function is useful for iterating over results without having to manually
|
||||
// specify the cursor and pagination order and max number of results
|
||||
func (store *WakuStore) Next(ctx context.Context, r *Result) (*Result, error) {
|
||||
q := &pb.HistoryQuery{
|
||||
PubsubTopic: r.query.PubsubTopic,
|
||||
|
@ -641,7 +651,7 @@ func (store *WakuStore) findLastSeen() float64 {
|
|||
return lastSeenTime
|
||||
}
|
||||
|
||||
// resume proc retrieves the history of waku messages published on the default waku pubsub topic since the last time the waku store node has been online
|
||||
// Resume retrieves the history of waku messages published on the default waku pubsub topic since the last time the waku store node has been online
|
||||
// messages are stored in the store node's messages field and in the message db
|
||||
// the offline time window is measured as the difference between the current time and the timestamp of the most recent persisted waku message
|
||||
// an offset of 20 second is added to the time window to count for nodes asynchrony
|
||||
|
@ -649,7 +659,6 @@ func (store *WakuStore) findLastSeen() float64 {
|
|||
// peerList indicates the list of peers to query from. The history is fetched from the first available peer in this list. Such candidates should be found through a discovery method (to be developed).
|
||||
// if no peerList is passed, one of the peers in the underlying peer manager unit of the store protocol is picked randomly to fetch the history from. The history gets fetched successfully if the dialed peer has been online during the queried time window.
|
||||
// the resume proc returns the number of retrieved messages if no error occurs, otherwise returns the error string
|
||||
|
||||
func (store *WakuStore) Resume(ctx context.Context, pubsubTopic string, peerList []peer.ID) (int, error) {
|
||||
if !store.started {
|
||||
return 0, errors.New("can't resume: store has not started")
|
||||
|
@ -695,7 +704,7 @@ func (store *WakuStore) Resume(ctx context.Context, pubsubTopic string, peerList
|
|||
}
|
||||
|
||||
for _, msg := range response.Messages {
|
||||
store.storeMessage(pubsubTopic, msg)
|
||||
store.storeMessage(protocol.NewEnvelope(msg, pubsubTopic))
|
||||
}
|
||||
|
||||
log.Info("Retrieved messages since the last online time: ", len(response.Messages))
|
||||
|
@ -705,14 +714,15 @@ func (store *WakuStore) Resume(ctx context.Context, pubsubTopic string, peerList
|
|||
|
||||
// TODO: queryWithAccounting
|
||||
|
||||
func (w *WakuStore) Stop() {
|
||||
w.started = false
|
||||
// Stop closes the store message channel and removes the protocol stream handler
|
||||
func (store *WakuStore) Stop() {
|
||||
store.started = false
|
||||
|
||||
if w.MsgC != nil {
|
||||
close(w.MsgC)
|
||||
if store.MsgC != nil {
|
||||
close(store.MsgC)
|
||||
}
|
||||
|
||||
if w.h != nil {
|
||||
w.h.RemoveStreamHandler(StoreID_v20beta3)
|
||||
if store.h != nil {
|
||||
store.h.RemoveStreamHandler(StoreID_v20beta3)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/status-im/go-waku/waku/v2/protocol"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/status-im/go-waku/waku/v2/utils"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -15,7 +16,7 @@ func TestIndexComputation(t *testing.T) {
|
|||
Timestamp: utils.GetUnixEpoch(),
|
||||
}
|
||||
|
||||
idx, err := computeIndex(msg)
|
||||
idx, err := computeIndex(protocol.NewEnvelope(msg, "test"))
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, idx.ReceiverTime)
|
||||
require.Equal(t, msg.Timestamp, idx.SenderTime)
|
||||
|
@ -27,7 +28,7 @@ func TestIndexComputation(t *testing.T) {
|
|||
Timestamp: 123,
|
||||
ContentTopic: "/waku/2/default-content/proto",
|
||||
}
|
||||
idx1, err := computeIndex(msg1)
|
||||
idx1, err := computeIndex(protocol.NewEnvelope(msg1, "test"))
|
||||
require.NoError(t, err)
|
||||
|
||||
msg2 := &pb.WakuMessage{
|
||||
|
@ -35,7 +36,7 @@ func TestIndexComputation(t *testing.T) {
|
|||
Timestamp: 123,
|
||||
ContentTopic: "/waku/2/default-content/proto",
|
||||
}
|
||||
idx2, err := computeIndex(msg2)
|
||||
idx2, err := computeIndex(protocol.NewEnvelope(msg2, "test"))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, idx1.Digest, idx2.Digest)
|
||||
|
@ -174,7 +175,7 @@ func TestForwardPagination(t *testing.T) {
|
|||
require.Equal(t, uint64(0), newPagingInfo.PageSize)
|
||||
|
||||
// test for an invalid cursor
|
||||
invalidIndex, err := computeIndex(&pb.WakuMessage{Payload: []byte{255, 255, 255}})
|
||||
invalidIndex, err := computeIndex(protocol.NewEnvelope(&pb.WakuMessage{Payload: []byte{255, 255, 255}}, "test"))
|
||||
require.NoError(t, err)
|
||||
pagingInfo = &pb.PagingInfo{PageSize: 10, Cursor: invalidIndex, Direction: pb.PagingInfo_FORWARD}
|
||||
messages, newPagingInfo = paginateWithoutIndex(msgList, pagingInfo)
|
||||
|
@ -258,7 +259,7 @@ func TestBackwardPagination(t *testing.T) {
|
|||
require.Equal(t, uint64(0), newPagingInfo.PageSize)
|
||||
|
||||
// test for an invalid cursor
|
||||
invalidIndex, err := computeIndex(&pb.WakuMessage{Payload: []byte{255, 255, 255}})
|
||||
invalidIndex, err := computeIndex(protocol.NewEnvelope(&pb.WakuMessage{Payload: []byte{255, 255, 255}}, "test"))
|
||||
require.NoError(t, err)
|
||||
pagingInfo = &pb.PagingInfo{PageSize: 10, Cursor: invalidIndex, Direction: pb.PagingInfo_BACKWARD}
|
||||
messages, newPagingInfo = paginateWithoutIndex(msgList, pagingInfo)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/status-im/go-waku/waku/persistence"
|
||||
"github.com/status-im/go-waku/waku/persistence/sqlite"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/status-im/go-waku/waku/v2/utils"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -36,7 +37,7 @@ func TestStorePersistence(t *testing.T) {
|
|||
Timestamp: utils.GetUnixEpoch(),
|
||||
}
|
||||
|
||||
s1.storeMessage(defaultPubSubTopic, msg)
|
||||
s1.storeMessage(protocol.NewEnvelope(msg, defaultPubSubTopic))
|
||||
|
||||
s2 := NewWakuStore(dbStore)
|
||||
s2.fetchDBRecords(ctx)
|
||||
|
@ -44,5 +45,5 @@ func TestStorePersistence(t *testing.T) {
|
|||
require.Equal(t, msg, s2.messages[0].msg)
|
||||
|
||||
// Storing a duplicated message should not crash. It's okay to generate an error log in this case
|
||||
s1.storeMessage(defaultPubSubTopic, msg)
|
||||
s1.storeMessage(protocol.NewEnvelope(msg, defaultPubSubTopic))
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/status-im/go-waku/tests"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol"
|
||||
"github.com/status-im/go-waku/waku/v2/protocol/pb"
|
||||
"github.com/status-im/go-waku/waku/v2/utils"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -17,8 +18,8 @@ func TestStoreQuery(t *testing.T) {
|
|||
msg2 := tests.CreateWakuMessage("2", utils.GetUnixEpoch())
|
||||
|
||||
s := NewWakuStore(nil)
|
||||
s.storeMessage(defaultPubSubTopic, msg1)
|
||||
s.storeMessage(defaultPubSubTopic, msg2)
|
||||
s.storeMessage(protocol.NewEnvelope(msg1, defaultPubSubTopic))
|
||||
s.storeMessage(protocol.NewEnvelope(msg2, defaultPubSubTopic))
|
||||
|
||||
response := s.FindMessages(&pb.HistoryQuery{
|
||||
ContentFilters: []*pb.ContentFilter{
|
||||
|
@ -44,9 +45,9 @@ func TestStoreQueryMultipleContentFilters(t *testing.T) {
|
|||
|
||||
s := NewWakuStore(nil)
|
||||
|
||||
s.storeMessage(defaultPubSubTopic, msg1)
|
||||
s.storeMessage(defaultPubSubTopic, msg2)
|
||||
s.storeMessage(defaultPubSubTopic, msg3)
|
||||
s.storeMessage(protocol.NewEnvelope(msg1, defaultPubSubTopic))
|
||||
s.storeMessage(protocol.NewEnvelope(msg2, defaultPubSubTopic))
|
||||
s.storeMessage(protocol.NewEnvelope(msg3, defaultPubSubTopic))
|
||||
|
||||
response := s.FindMessages(&pb.HistoryQuery{
|
||||
ContentFilters: []*pb.ContentFilter{
|
||||
|
@ -77,9 +78,9 @@ func TestStoreQueryPubsubTopicFilter(t *testing.T) {
|
|||
msg3 := tests.CreateWakuMessage(topic3, utils.GetUnixEpoch())
|
||||
|
||||
s := NewWakuStore(nil)
|
||||
s.storeMessage(pubsubTopic1, msg1)
|
||||
s.storeMessage(pubsubTopic2, msg2)
|
||||
s.storeMessage(pubsubTopic2, msg3)
|
||||
s.storeMessage(protocol.NewEnvelope(msg1, pubsubTopic1))
|
||||
s.storeMessage(protocol.NewEnvelope(msg2, pubsubTopic2))
|
||||
s.storeMessage(protocol.NewEnvelope(msg3, pubsubTopic2))
|
||||
|
||||
response := s.FindMessages(&pb.HistoryQuery{
|
||||
PubsubTopic: pubsubTopic1,
|
||||
|
@ -109,9 +110,9 @@ func TestStoreQueryPubsubTopicNoMatch(t *testing.T) {
|
|||
msg3 := tests.CreateWakuMessage(topic3, utils.GetUnixEpoch())
|
||||
|
||||
s := NewWakuStore(nil)
|
||||
s.storeMessage(pubsubTopic2, msg1)
|
||||
s.storeMessage(pubsubTopic2, msg2)
|
||||
s.storeMessage(pubsubTopic2, msg3)
|
||||
s.storeMessage(protocol.NewEnvelope(msg1, pubsubTopic2))
|
||||
s.storeMessage(protocol.NewEnvelope(msg2, pubsubTopic2))
|
||||
s.storeMessage(protocol.NewEnvelope(msg3, pubsubTopic2))
|
||||
|
||||
response := s.FindMessages(&pb.HistoryQuery{
|
||||
PubsubTopic: pubsubTopic1,
|
||||
|
@ -131,9 +132,9 @@ func TestStoreQueryPubsubTopicAllMessages(t *testing.T) {
|
|||
msg3 := tests.CreateWakuMessage(topic3, utils.GetUnixEpoch())
|
||||
|
||||
s := NewWakuStore(nil)
|
||||
s.storeMessage(pubsubTopic1, msg1)
|
||||
s.storeMessage(pubsubTopic1, msg2)
|
||||
s.storeMessage(pubsubTopic1, msg3)
|
||||
s.storeMessage(protocol.NewEnvelope(msg1, pubsubTopic1))
|
||||
s.storeMessage(protocol.NewEnvelope(msg2, pubsubTopic1))
|
||||
s.storeMessage(protocol.NewEnvelope(msg3, pubsubTopic1))
|
||||
|
||||
response := s.FindMessages(&pb.HistoryQuery{
|
||||
PubsubTopic: pubsubTopic1,
|
||||
|
@ -153,7 +154,7 @@ func TestStoreQueryForwardPagination(t *testing.T) {
|
|||
for i := 0; i < 10; i++ {
|
||||
msg := tests.CreateWakuMessage(topic1, utils.GetUnixEpoch())
|
||||
msg.Payload = []byte{byte(i)}
|
||||
s.storeMessage(pubsubTopic1, msg)
|
||||
s.storeMessage(protocol.NewEnvelope(msg, pubsubTopic1))
|
||||
}
|
||||
|
||||
response := s.FindMessages(&pb.HistoryQuery{
|
||||
|
@ -181,7 +182,7 @@ func TestStoreQueryBackwardPagination(t *testing.T) {
|
|||
Version: 0,
|
||||
Timestamp: utils.GetUnixEpoch(),
|
||||
}
|
||||
s.storeMessage(pubsubTopic1, msg)
|
||||
s.storeMessage(protocol.NewEnvelope(msg, pubsubTopic1))
|
||||
|
||||
}
|
||||
|
||||
|
@ -208,7 +209,7 @@ func TestTemporalHistoryQueries(t *testing.T) {
|
|||
contentTopic = "2"
|
||||
}
|
||||
msg := tests.CreateWakuMessage(contentTopic, float64(i))
|
||||
s.storeMessage("test", msg)
|
||||
s.storeMessage(protocol.NewEnvelope(msg, "test"))
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,14 @@ package utils
|
|||
|
||||
import "time"
|
||||
|
||||
func GetUnixEpochFrom(now func() time.Time) float64 {
|
||||
return float64(now().UnixNano()) / float64(time.Second)
|
||||
// GetUnixEpoch converts a time into a unix timestamp with the integer part
|
||||
// representing seconds and the decimal part representing subseconds
|
||||
func GetUnixEpochFrom(now time.Time) float64 {
|
||||
return float64(now.UnixNano()) / float64(time.Second)
|
||||
}
|
||||
|
||||
// GetUnixEpoch returns the current time in unix timestamp with the integer part
|
||||
// representing seconds and the decimal part representing subseconds
|
||||
func GetUnixEpoch() float64 {
|
||||
return GetUnixEpochFrom(time.Now)
|
||||
return GetUnixEpochFrom(time.Now())
|
||||
}
|
||||
|
|
|
@ -9,10 +9,7 @@ import (
|
|||
|
||||
func TestGetUnixEpochFrom(t *testing.T) {
|
||||
loc := time.UTC
|
||||
timeFn := func() time.Time {
|
||||
return time.Date(2019, 1, 1, 0, 0, 0, 0, loc)
|
||||
}
|
||||
timestamp := GetUnixEpochFrom(timeFn)
|
||||
timestamp := GetUnixEpochFrom(time.Date(2019, 1, 1, 0, 0, 0, 0, loc))
|
||||
|
||||
require.Equal(t, float64(1546300800), timestamp)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue