Transaction

166AF4F1890355…B8280292E5EE

Block 166,449 · index 0 · indexed

Summary

Hash
166AF4F1890355C5CB8771C5B9FE83AEBE1FB2FBA2D6CC7C7E9CB8280292E5EE
Block
166,449
Size
6148 bytes
Gas used
7,948,622 / 9,000,000
Fee
9000 ugnot
Status
success

Messages

Arguments · 11

  1. #1message
  2. #2README.md
  3. #3# Message Package Package provides a simple message broker implementation. The message broker is a Pub/Sub one. It implements two different interfaces, `Publisher` and `Subscriber`, which are also defined within this package. Published messages contain the topic where they are published and optional message data. Subscribing to the `TopicAll` topic triggers the callback for messages published to any topic. Repository can be found at [jeronimoalbi/gnome](https://github.com/jeronimoalbi/gnome), as part of `jeronimoalbi`'s Gno smart contracts monorepo. ## Usage [embedmd]:# (filetests/readme_filetest.gno go) ```go package main import "gno.land/p/jeronimoalbi/message" func main() { broker := message.NewBroker() // Subscribe to an event subID, err := broker.Subscribe("EventName", func(msg message.Message) { println("EventName has been triggered:", msg.Data.(string)) }) if err != nil { panic(err) } // Publish an event err = broker.Publish("EventName", "Example event data") if err != nil { panic(err) } // Unsubscribe from the event unsubscribed, err := broker.Unsubscribe("EventName", subID) if err != nil { panic(err) } if !unsubscribed { panic("subscription not found") } // Nothing is triggered after unsubscribing err = broker.Publish("EventName", "Ignored event data") if err != nil { panic(err) } } // Output: // EventName has been triggered: Example event data ```
  4. #4broker.gno
  5. #5package message import ( "errors" "strings" "gno.land/p/moul/ulist/v0" "gno.land/p/nt/bptree/v0" ) var ( // ErrInvalidTopic is triggered when an invalid topic is used. ErrInvalidTopic = errors.New("invalid topic") // ErrRequiredCallback is triggered when subscribing without a callback. ErrRequiredCallback = errors.New("message callback is required") // ErrRequiredSubscriptionID is triggered when unsubscribing without an ID. ErrRequiredSubscriptionID = errors.New("message sibscription ID is required") // ErrRequiredTopic is triggered when (un)subscribing without a topic. ErrRequiredTopic = errors.New("message topic is required") ) // NewBroker creates a new message broker. func NewBroker() *Broker { return &Broker{ callbacks: bptree.NewBPTree32(), } } // Broker is a message broker that handles subscriptions and message publishing. type Broker struct { callbacks *bptree.BPTree // string(topic) -> *ulist.List(Callback) } // Topics returns the list of current subscription topics. func (b *Broker) Topics() []Topic { var topics []Topic b.callbacks.Iterate("", "", func(k string, _ any) bool { topic := Topic(k) if topic == TopicAll { // Skip catchall topic from the list return false } topics = append(topics, topic) return false }) return topics } // Subscribe subscribes to messages published for a topic. // It returns the callback ID within the topic. func (b *Broker) Subscribe(topic Topic, cb Callback) (id int, _ error) { key := strings.TrimSpace(string(topic)) if key == "" { return 0, ErrRequiredTopic } if cb == nil { return 0, ErrRequiredCallback } callbacks, _ := b.callbacks.Get(key).(*ulist.List) if callbacks == nil { callbacks = ulist.New() } callbacks.Append(cb) b.callbacks.Set(key, callbacks) return callbacks.TotalSize(), nil } // Unsubscribe unsubscribes a callback from a message topic. // ID is the callback ID within the topic, returned on subscription. func (b *Broker) Unsubscribe(topic Topic, id int) (unsubscribed bool, _ error) { key := strings.TrimSpace(string(topic)) if key == "" { return false, ErrRequiredTopic } if id == 0 { return false, ErrRequiredSubscriptionID } callbacks, ok := b.callbacks.Get(key).(*ulist.List) if !ok { return false, errors.New("message topic not found: " + key) } i := id - 1 return callbacks.Delete(i) == nil, nil } // Publish publishes a message for a topic. func (b *Broker) Publish(topic Topic, data any) error { if topic == TopicAll { return ErrInvalidTopic } key := strings.TrimSpace(string(topic)) if key == "" { return ErrRequiredTopic } iterCb := func(_ int, v any) bool { cb := v.(Callback) cb(Message{topic, data}) return false } // Trigger callbacks subscribed to current topic if callbacks, ok := b.callbacks.Get(key).(*ulist.List); ok { callbacks.Iterator(0, callbacks.Size(), iterCb) } // Trigger callbacks subscribed to all topics if callbacks, ok := b.callbacks.Get(string(TopicAll)).(*ulist.List); ok { callbacks.Iterator(0, callbacks.Size(), iterCb) } return nil }
  6. #6gnomod.toml
  7. #7module = "gno.land/p/jeronimoalbi/message" gno = "0.9"
  8. #8message.gno
  9. #9// Package message provides a simple message broker implementation. package message // TopicAll defines a topic for all types of message. // This topic can be used to subscribe to message for all topics. const TopicAll Topic = "*" type ( // Topic defines a type for message topics. Topic string // Callback defines a type for message callbacks. Callback func(Message) // Message defines a type for published messages. Message struct { // Topic is the message topic. Topic Topic // Data contains optional message data. Data any } // Publisher defines an interface for message publishers. Publisher interface { // Publish publishes a message for a topic. Publish(_ Topic, data any) error } // Subscriber defines an interface for message subscribers. Subscriber interface { // Subscribe subscribes to messages published for a topic. // It returns the callback ID within the topic. Subscribe(Topic, Callback) (id int, _ error) // Unsubscribe unsubscribes a callback from a message topic. // ID is the callback ID within the topic, returned on subscription. Unsubscribe(_ Topic, id int) (unsubscribed bool, _ error) } )
  10. #10/gno.MemPackageType
  11. #11 MPUserAll

Result log

msg:0,success:true,log:,events:[]