Skip to content

Commit

Permalink
update our events
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanfaerman committed Jan 31, 2024
1 parent 77e33b9 commit e115a1c
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 60 deletions.
28 changes: 15 additions & 13 deletions internal/events/account.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package events

func init() {
register[AccountCreated]("account.created")
register[AccountProfileUpdated]("account.profile_updated")
register[AccountSessionOpened]("account.session_opened")
}

type (
AccountCreated struct {
ID int64
Email string
Email string `json:"email"`
ID int64 `json:"id"`
}

AccountProfileUpdated struct {
ID int64
Name string
About string
Callsign string
Name string `json:"name"`
About string `json:"about"`
Callsign string `json:"callsign"`
ID int64 `json:"id"`
}

AccountSessionOpened struct {
ID int64
UserAgent string
IP string
UserAgent string `json:"user_agent"`
IP string `json:"ip"`
ID int64 `json:"id"`
}
)

func (AccountCreated) Event() string { return "account.created" }
func (AccountProfileUpdated) Event() string { return "account.profile_updated" }
func (AccountSessionOpened) Event() string { return "account.session_opened" }
55 changes: 53 additions & 2 deletions internal/events/event.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@
package events

type Event interface {
Event() string
import (
"encoding/gob"
"encoding/json"
"fmt"
)

// A registrant is a type registered with the event system
// and available for decoding.
type registrant struct {
new func() any
friendly string // a friendly name for the type, e.g. "user.session_created"
name string // the name of the type, e.g. "events.UserCreated"
}

// Registry holds the registered types.
var registry = make(map[string]registrant)

// Register a type with the event system. We collect the name of the event,
// a friendly type for user/consumer reference, and a function that returns a pointer
// to a new instance of the type. We also register the type with gob, should
// a consumer wish to encode/decode the event to/from a binary format.
//
// The friendly name shouldn't be used for anything other than display. Internal
// references should use the name field.
func register[K any](friendly string) {
gob.Register(*new(K))

name := fmt.Sprintf("%T", *new(K))
registry[name] = registrant{
name: name,
new: func() any {
return new(K)
},
friendly: friendly,
}
}

// Decode an event from JSON. The kind is the name of the event, and the data is the
// JSON payload. This is useful for decoding events from the database or queue.
func Decode(kind string, data []byte) (any, error) {
k := registry[kind].new()
return k, json.Unmarshal(data, k)
}

// FriendlyNameFor returns the friendly name for the event type, as provided
// during registration.
func FriendlyNameFor(kind string) string {
return registry[kind].friendly
}

// NameFor returns the name of the event type, e.g. "events.UserCreated".
func NameFor(kind string) string {
return registry[kind].name
}
75 changes: 30 additions & 45 deletions internal/events/net.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package events

import (
"encoding/gob"
"errors"
"time"
)

func init() {
gob.Register(NetCheckinHeard{})
gob.Register(NetCheckinVerified{})
gob.Register(NetCheckinAcked{})
gob.Register(NetCheckinCorrected{})
gob.Register(NetCheckinRevoked{})

gob.Register(NetSessionScheduled{})
gob.Register(NetSessionOpened{})
gob.Register(NetSessionClosed{})
register[NetCheckinHeard]("net.checkin_heard")
register[NetCheckinVerified]("net.checkin_verified")
register[NetCheckinAcked]("net.checkin_acked")
register[NetCheckinCorrected]("net.checkin_corrected")
register[NetCheckinRevoked]("net.checkin_revoked")

register[NetSessionScheduled]("net.session_scheduled")
register[NetSessionOpened]("net.session_opened")
register[NetSessionClosed]("net.session_closed")
}

var (
Expand All @@ -29,57 +28,52 @@ type (
// NetCheckinHeard is a struct that contains the information about a checkin
// as it was heard by the net control operator.
NetCheckinHeard struct {
ID string // a random identifier, ideally a ULID

Callsign string
Name string
Location string
Kind string // e.g. models.EventCheckinKindRoutine
Traffic int
ID string `json:"id"` // a random identifier, ideally a ULID
Callsign string `json:"callsign"`
Name string `json:"name"`
Location string `json:"location"`
Kind string `json:"kind"` // e.g. models.EventCheckinKindRoutine
Traffic int `json:"traffic"`
}

// NetCheckinVerified is a struct that contains the information about a checkin
// as it was verified against a licensing authority.
NetCheckinVerified struct {
ID string // should match the ID from NetCheckinHeard

Callsign string
Name string
Location string

ErrorType string // e.g. hamdb.ErrNotFound, ErrClub

CallsignID int64 // reference a record in the database
ID string `json:"id"` // should match the ID from NetCheckinHeard
Callsign string `json:"callsign"`
Name string `json:"name"`
Location string `json:"location"`
ErrorType string `json:"error_type"` // e.g. hamdb.ErrNotFound, ErrClub
CallsignID int64 `json:"callsign_id"` // reference a record in the database
}

// NetCheckinAcked is a struct that contains the information about a checkin
// as it was acknowledged by the net control operator.
NetCheckinAcked struct {
ID string // should match the ID from NetCheckinHeard
ID string `json:"id"` // should match the ID from NetCheckinHeard
}

// NetCheckinCorrected is a struct that contains the information about a checkin
// as it was corrected by the net control operator.
NetCheckinCorrected struct {
ID string // should match the ID from NetCheckinHeard

Callsign string
Name string
Location string
Kind string
Traffic int
ID string `json:"id"` // should match the ID from NetCheckinHeard
Callsign string `json:"callsign"`
Name string `json:"name"`
Location string `json:"location"`
Kind string `json:"kind"`
Traffic int `json:"traffic"`
}

// NetCheckinRevoked is a struct that contains the information about a checkin
// as it was revoked by the net control operator.
NetCheckinRevoked struct {
ID string // should match the ID from NetCheckinHeard
ID string `json:"id"` // should match the ID from NetCheckinHeard
}

// NetSessionScheduled occurs when a net session is scheduled. Often occurs
// when it is first created.
NetSessionScheduled struct {
At time.Time
At time.Time `json:"at"`
}

// NetSessionOpened occurs when a net session is opened.
Expand All @@ -88,12 +82,3 @@ type (
// NetSessionClosed occurs when a net session is closed.
NetSessionClosed struct{}
)

func (NetCheckinHeard) Event() string { return "checkin.heard" }
func (NetCheckinVerified) Event() string { return "checkin.verified" }
func (NetCheckinAcked) Event() string { return "checkin.acked" }
func (NetCheckinCorrected) Event() string { return "checkin.corrected" }
func (NetCheckinRevoked) Event() string { return "checkin.revoked" }
func (NetSessionScheduled) Event() string { return "session.scheduled" }
func (NetSessionOpened) Event() string { return "session.opened" }
func (NetSessionClosed) Event() string { return "session.closed" }

0 comments on commit e115a1c

Please sign in to comment.