resonate icon indicating copy to clipboard operation
resonate copied to clipboard

Add Announcements

Open dtornow opened this issue 10 months ago • 3 comments

Describe the problem you are facing

Resonate's Deterministic Simulation Testing cannot observe the Resonate Server beyond the request/response API. E.g. the Deterministic Simulation Testing cannot observe if notifications are actually sent.

Describe the solution you'd like

P-Lang style announcements & monitors. With announcements and monitors, DST will be able to verify that e.g. announcements are sent if a corresponding subscription exists.

Implementation Details

Step 1

Create a package announcements.

Step 2

Define an interface Announcement with a function

type Announcement interface {
    Announce(data map[string]string)
}

Step 3

Define two different implementations:

  • NopAnnouncement
  • DstAnnouncement

Step 4

Use a package-level private variable to hold a singleton instance. Instantiate the correct singleton instance based on config parameter on startup e.g.

package announcements

import "sync"

var (
    instance Announcement
    once     sync.Once
)

func Initialize(envType EnvironmentType) {
    once.Do(func() {
        switch envType {
        case Nop:
            instance = &NopAnnouncement{}
        case Dst:
            instance = &DstAnnouncement{}
        default:
            // Handle default case or throw an error
        }
    })
}

// Additional code to define EnvironmentType, NopAnnouncement, and DstAnnouncement follows...

Step 5

Implement the interface

  • Nop This will simply implement the Announce method without performing any operations.
  • Dst This will need to safely add the announcement data to an array for later verification. Ensure thread safety

dtornow avatar Apr 01 '24 02:04 dtornow

The network is a good candidate to add a first announcement

https://github.com/resonatehq/resonate/blob/7935e1cae3c90e04152d23f2170acdb101a73946/internal/kernel/t_aio/network.go#L22

dtornow avatar Apr 01 '24 02:04 dtornow

Add a custom event struct. The only required parameter is type, everything else is a key value map

type Event struct {
	Type string
	data map[string]interface{}
}


func NewEvent(type string, initialData ...map[string]interface{}) *Event {
	var data map[string]interface{}
	if len(initialData) > 0 {
		data = initialData[0] // Use the first map provided if any.
	} else {
		data = make(map[string]interface{}) 
	}

	return &Event{
		Type: eventType,
		data: data
	}
}

// Set adds or updates a key with a given value.
func (e *Event) Set(key string, value interface{}) {
	e.data[key] = value
}

// Get tries to retrieve a value of the specified type T from the event data. It returns the zero value and an error if the type does not match.
func [T any](e *Event) Get[T any](key string) (T, error) {
	value, exists := e.data[key]
	if !exists {
		var zero T
		panic("key %s does not exist in event of type %s", key, e.Type)
	}

	typedValue, ok := value.(T)
	if !ok {
		panic("value at key %s is not of the requested type in event of type %s", key, e.Type)
	}

	return typedValue, nil
}

dtornow avatar Apr 02 '24 02:04 dtornow

Regarding announcements: The announcement (the event) should contain all (relevant) application level information. For example, in the context of networking, the event should contain the url, http method, and http body

dtornow avatar Apr 02 '24 02:04 dtornow