Skip to content

Instantly share code, notes, and snippets.

@Krule
Created December 1, 2022 16:13
Show Gist options
  • Select an option

  • Save Krule/7e5cfe4ba3edfa0c960bcbfe7fe2ca72 to your computer and use it in GitHub Desktop.

Select an option

Save Krule/7e5cfe4ba3edfa0c960bcbfe7fe2ca72 to your computer and use it in GitHub Desktop.

Revisions

  1. Krule created this gist Dec 1, 2022.
    144 changes: 144 additions & 0 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,144 @@
    // Event is a representation of a significant happening in the gang's history.
    type Event struct {
    Timestamp time.Time
    Name string
    Data map[string]interface{}
    }

    // EventLog is a record of all the significant happenings in the gang's history.
    type EventLog []Event

    // NewEventLog creates a new event log.
    func NewEventLog() EventLog {
    return EventLog{}
    }

    // AddEvent adds a new event to the event log.
    func (log *EventLog) AddEvent(event Event) {
    *log = append(*log, event)
    }

    // GetEventsSince returns all the events in the log that have occurred since the given time.
    func (log EventLog) GetEventsSince(since time.Time) EventLog {
    var events EventLog
    for _, event := range log {
    if event.Timestamp.After(since) {
    events = append(events, event)
    }
    }
    return events
    }

    // Command represents an action that modifies the state of the gang.
    type Command struct {
    Name string
    Data map[string]interface{}
    }

    // CommandHandler is responsible for executing commands and generating events.
    type CommandHandler struct {
    eventLog *EventLog
    }

    // NewCommandHandler creates a new command handler.
    func NewCommandHandler(eventLog *EventLog) *CommandHandler {
    return &CommandHandler{eventLog: eventLog}
    }

    // HandleCommand executes the given command and generates events as a result.
    func (h *CommandHandler) HandleCommand(cmd Command) ([]Event, error) {
    var events []Event
    switch cmd.Name {
    case "add_member":
    memberName, ok := cmd.Data["name"].(string)
    if !ok {
    return nil, fmt.Errorf("invalid command data: missing member name")
    }
    events = append(events, Event{
    Timestamp: time.Now(),
    Name: "member_added",
    Data: map[string]interface{}{
    "name": memberName,
    },
    })
    case "add_shipment":
    shipmentID, ok := cmd.Data["id"].(string)
    if !ok {
    return nil, fmt.Errorf("invalid command data: missing shipment ID")
    }
    events = append(events, Event{
    Timestamp: time.Now(),
    Name: "shipment_added",
    Data: map[string]interface{}{
    "id": shipmentID,
    },
    })
    case "whack_rival":
    rivalName, ok := cmd.Data["name"].(string)
    if !ok {
    return nil, fmt.Errorf("invalid command data: missing rival name")
    }
    events = append(events, Event{
    Timestamp: time.Now(),
    Name: "rival_whacked",
    Data: map[string]interface{}{
    "name": rivalName,
    },
    })
    default:
    return nil, fmt.Errorf("unknown command: %s", cmd.Name)
    }
    return events, nil
    }

    // QueryHandler is responsible for generating views of the gang's state.
    type QueryHandler struct {
    eventLog EventLog
    }

    // NewQueryHandler creates a new query handler.
    func NewQueryHandler(eventLog EventLog) *QueryHandler {
    return &QueryHandler{eventLog: eventLog}
    }

    // HandleQuery generates a view of the gang's state based on the given query.
    func (h *QueryHandler) HandleQuery(query Query) (map[string]interface{}, error) {
    switch query.Name {
    case "members":
    return h.getMembers(), nil
    case "shipments":
    return h.getShipments(), nil
    default:
    return nil, fmt.Errorf("unknown query: %s", query.Name)
    }
    }

    func (h *QueryHandler) getMembers() map[string]interface{} {
    members := []string{}
    for _, event := range h.eventLog {
    if event.Name == "member_added" {
    memberName, ok := event.Data["name"].(string)
    if ok {
    members = append(members, memberName)
    }
    }
    }
    return map[string]interface{}{
    "members": members,
    }
    }

    func (h *QueryHandler) getShipments() map[string]interface{} {
    shipments := []string{}
    for _, event := range h.eventLog {
    if event.Name == "shipment_added" {
    shipmentID, ok := event.Data["id"].(string)
    if ok {
    shipments = append(shipments, shipmentID)
    }
    }
    }
    return map[string]interface{}{
    "shipments": shipments,
    }
    }