github.com/emitter-io/go/v2@v2.1.0/store.go (about)

     1  package emitter
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/eclipse/paho.mqtt.golang/packets"
     8  )
     9  
    10  // In-memory storage implementation
    11  type store struct {
    12  	sync.RWMutex
    13  	messages map[string]*packet
    14  }
    15  
    16  // Response represents a generic response sent by the broker.
    17  type Response interface {
    18  	RequestID() uint16
    19  }
    20  
    21  // The control packet with an optional error and a response.
    22  type packet struct {
    23  	packets.ControlPacket
    24  	callback chan Response
    25  }
    26  
    27  // newStore creates a new message storage layer.
    28  func newErrorStore() *store {
    29  	store := &store{
    30  		messages: make(map[string]*packet),
    31  	}
    32  	return store
    33  }
    34  
    35  // Open initializes a MemoryStore instance.
    36  func (store *store) Open() {}
    37  
    38  // Put takes a key and a pointer to a Message and stores the message.
    39  func (store *store) Put(key string, message packets.ControlPacket) {
    40  	store.Lock()
    41  	defer store.Unlock()
    42  
    43  	store.messages[key] = &packet{
    44  		ControlPacket: message,
    45  	}
    46  }
    47  
    48  // Get takes a key and looks in the store for a matching Message
    49  // returning either the Message pointer or nil.
    50  func (store *store) Get(key string) packets.ControlPacket {
    51  	store.RLock()
    52  	defer store.RUnlock()
    53  	return store.messages[key]
    54  }
    55  
    56  // All returns a slice of strings containing all the keys currently
    57  // in the MemoryStore.
    58  func (store *store) All() []string {
    59  	store.RLock()
    60  	defer store.RUnlock()
    61  
    62  	keys := []string{}
    63  	for k := range store.messages {
    64  		keys = append(keys, k)
    65  	}
    66  	return keys
    67  }
    68  
    69  // Del takes a key, searches the MemoryStore and if the key is found
    70  // deletes the Message pointer associated with it.
    71  func (store *store) Del(key string) {
    72  	store.Lock()
    73  	defer store.Unlock()
    74  
    75  	m := store.messages[key]
    76  	if m != nil && m.callback == nil {
    77  		delete(store.messages, key)
    78  	}
    79  }
    80  
    81  // Close will disallow modifications to the state of the store.
    82  func (store *store) Close() {}
    83  
    84  // Reset eliminates all persisted message data in the store.
    85  func (store *store) Reset() {
    86  	store.Lock()
    87  	defer store.Unlock()
    88  	store.messages = make(map[string]*packet)
    89  }
    90  
    91  // PutCallback adds a callback channel to a message.
    92  func (store *store) PutCallback(id uint16) <-chan Response {
    93  	store.Lock()
    94  	defer store.Unlock()
    95  
    96  	key := outboundKeyFromMID(id)
    97  	if m, ok := store.messages[key]; ok && m != nil {
    98  		m.callback = make(chan Response, 1)
    99  		return m.callback
   100  	}
   101  	return nil
   102  }
   103  
   104  // NotifyResponse notifies a response on a callback (if exists)
   105  func (store *store) NotifyResponse(id uint16, response Response) bool {
   106  	store.RLock()
   107  	defer store.RUnlock()
   108  
   109  	key := outboundKeyFromMID(id)
   110  	if m, ok := store.messages[key]; ok && m != nil {
   111  		m.callback <- response
   112  		close(m.callback)
   113  		delete(store.messages, key)
   114  		return true
   115  	}
   116  	return false
   117  }
   118  
   119  // Return a string of the form "o.[id]"
   120  func outboundKeyFromMID(id uint16) string {
   121  	return fmt.Sprintf("o.%d", id)
   122  }