Giter Site home page Giter Site logo

message's Introduction

Test Build Coverage Status Go Report Card Issues Issues

Message Interface

An interface to add domain events and messages to your Go projects!

View Examples · Report Bug · Request Feature

About the Project

Why?

As a project matures, requirements and the technical environment evolve, it is painful to realise that deeply embedded dependencies like loggers or message systems have to be replaced. This is especially true for Go, that is not offering standard abstractions for these use cases. Thus, it is a helpful practise to hide external libraries behind an application specific interface.

This is such an (opinionated) interface intended to be copied into your project.

Principles & Design Goals

The goal is a message interface, that can be implemented by multiple libraries as time progresses.
This repository explores what a good interface looks like for Go and provides an in memory reference implementation.

  1. Simplicity. The most important part is the simple interface. It provides just enough to send and receive messages in an application.
  2. Change resilient. Don't just import this project. Copy the interface into your app and use any of the available implementations, so your use cases and domain don't depend on any library in the future. Not even on this one.
  3. Developer convenience. With an emphasis on development speed and readable code this interface improves upon the pattern often seen with other libraries: marshalling and unmarshalling the message to and from []byte. This clutters your code with serialisation logic and can be hidden behind an interface.
type PubSub interface {
    Publish(ctx context.Context, eom EventOrMessage) error
    Subscribe(eom EventOrMessage, h HandlerFunc) (*Subscriber, error)
    Shutdown(ctx context.Context)
}

Examples

$ go get -u github.com/HTechHQ/message

Publish-Subscribe with messages

func main() {
    p := message.NewPubsubMem()
    ctx := context.Background()
   
    sub, _ := p.Subscribe(helloMessage{}, func(ctx context.Context, msg helloMessage) {
        fmt.Println(msg.Message)
    })
   
    p.Publish(ctx, helloMessage{"hello world!"})
    sub.Unsubscribe()
    p.Publish(ctx, helloMessage{"hello world!"})
   
    p.Shutdown(ctx)
    // output: hello world!
}

// helloMessage is a message passed from a publisher to potentially many subscribers.
type helloMessage struct {
    Message string
}

Publish-Subscribe with domain events

func main() {
    var publisher message.PubSub = message.NewPubsubMem()

    publisher.Subscribe(newUserRegistered{}, func(ctx context.Context, e newUserRegistered) {
        // log the registration of the new user
        fmt.Println(e.Username, e.Email, e.Settings, e.CreatedAt.Format("2006.01.02"))
    })
    publisher.Subscribe(newUserRegistered{}, func(ctx context.Context, e newUserRegistered) {
        fmt.Printf("Preparing welcome email for new user: %s to: %s\n", e.Username, e.Email)
     })

    publisher.Publish(context.Background(), newUserRegistered{
        Username:  "Max",
        Email:     "[email protected]",
        CreatedAt: time.Now(),
        Settings:  []string{"setting"},
    })

    publisher.Shutdown(context.Background())
    // output:
    // Max [setting] 2021.04.25
    // Preparing welcome email for new user: Max to: [email protected]
}

// newUserRegistered is the actual event that's fired after a new user got registered.
type newUserRegistered struct {
    Username  string
    Email     string
    CreatedAt time.Time
    Settings  []string
}

See all examples

Roadmap

Depending on your needs a persistent implementation, relying on something like NATS or Redis, might be good to support your desired semantics like at-least-once-delivery. PR welcome.

Also working on metrics and a queue expansion.

See the open issues for a list of proposed features (and known issues).

message's People

Contributors

htechhq avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.