modernice / goes

goes is an event-sourcing framework for Go.
https://goes.modernice.dev
Apache License 2.0
134 stars 12 forks source link

Add a way to force-refresh projections #4

Closed bounoable closed 3 years ago

bounoable commented 3 years ago

When a projection type embeds a *project.Progressor and the projection logic is changed, it may be necessary to invalidate the projections in the database.

Ideas

Trigger option

A Trigger option that forces a complete re-build could be provided:

package example

var schedule project.Schedule

schedule.Trigger(context.TODO(), project.Fully())

The above solution is quite low-level and would require developers to implement such re-builds themselves for every possible projection type they create.

Trigger option in combination with some kind of Schedule registry/list

package example

var schedule project.Schedule
var list project.ScheduleList

list.Trigger(context.TODO()) // trigger all Schedules in the list
list.Trigger(context.TODO(), project.Fully())

The above solution would only work within a single service.

Dedicated projection service in combination with CLI

A dedicated projection service could be provided that can be accessed through a CLI.

Projection service:

package main

func main() {
    svc := project.NewService()
    http.ListenAndServe(":8000", svc)
}

Some service with projections:

package main

func main() {
    var bus event.Bus
    var store event.Store

    client := project.NewClient(":8000")

    schedule := project.Continuously(bus, store, []string{"foo", "bar", "baz"})

    err := client.RegisterSchedule("example", schedule)
}

Rebuild using CLI:

goes projection rebuild -name example

Rebuild using API:

package main

func main() {
    var client *project.Client

    err := client.Trigger(context.TODO(), project.Fully())
}

Event-driven projection service in combination with CLI

Register Schedule in implementing service:

package main

func main() {
    var ebus event.Bus
    var estore event.Store
    var cbus command.Bus

    schedule := project.Continuously(ebus, estore, []string{"foo", "bar", "baz"})

    svc := project.NewService(cbus, project.RegisterSchedule("example", schedule))

    errs, err := svc.Run(context.TODO())
}

Rebuild using CLI:

goes projection rebuild -name example

Rebuild using API:

package main

func main() {
    var cbus command.Bus

    svc := project.NewService(cbus)

    err := svc.Trigger(context.TODO(), "example", project.Fully())
}