Skip to content

Commit

Permalink
[event] The way we consider an event has changed.
Browse files Browse the repository at this point in the history
- Before this `Event` MUST `Dispatch()` before its related logic, But we changed it to after its logic processed.
- Added more comments to clarify this change
- some other fixes and improvements
  • Loading branch information
OmidHekayati committed Nov 23, 2024
1 parent 092bd93 commit 2cce432
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 52 deletions.
17 changes: 8 additions & 9 deletions event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package event

import (
datatype_p "memar/datatype/protocol"
error_p "memar/error/protocol"
event_p "memar/event/protocol"
time_p "memar/time/protocol"
"memar/time/unix"
)
Expand All @@ -17,18 +17,17 @@ type Event struct {
time unix.Time
}

//memar:impl memar/computer/language/object/protocol.LifeCycle
//memar:impl memar/computer/capsule/protocol.LifeCycle
func (self *Event) Init(dt datatype_p.DataType, time unix.Time) {
self.dt = dt
self.time = time
}

//memar:impl memar/event/protocol.Event
//memar:impl memar/datatype/protocol.Field_DataType
func (self *Event) DataType() datatype_p.DataType { return self.dt }
func (self *Event) Time() time_p.Time { return &self.time }
func (self *Event) Cancelable() bool { return false }
func (self *Event) DefaultPrevented() bool { return false }
func (self *Event) Bubbles() bool { return false }

//memar:impl memar/event/protocol.Event_Methods
func (self *Event) PreventDefault() (err error_p.Error) { return nil }
//memar:impl memar/time/protocol.Field_Time
func (self *Event) Time() time_p.Time { return &self.time }

//memar:impl memar/math/logic/protocol.Equivalence
func (self *Event) Equivalence(with event_p.Event) bool { return self.DataType() == with.DataType() }
29 changes: 16 additions & 13 deletions event/protocol/event-target.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,39 @@ import (
)

// Target is a interface implemented to receive events and may have listeners for them.
// It MUST implement in each domain that need to dispatch, It means method only accept that domain event not other one.
//
// It MUST implement for each data-type in each domain that need to dispatch,
// It means method only accept that data-type event not any other one.
//
// Other frameworks:
// https://developer.mozilla.org/en-US/docs/Web/API/Target
type Target[E Event] interface {
// Appends an event listener for events whose type attribute value is type.
// The callback argument sets the callback that will be invoked when the event is dispatched.
// The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture.
//
// Other frameworks:
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
AddEventListener(callback EventListener[E]) (err error_p.Error)

// Removes the event listener in target's event listener list with the same type, callback, and options.
//
// Other frameworks:
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
RemoveEventListener(callback EventListener[E]) (err error_p.Error)

// DispatchEvent() or Raise() invokes event handlers synchronously(immediately).
// All applicable event handlers are called and return before DispatchEvent() returns.
// The terms "notify clients", "send notifications", "trigger notifications", and "fire notifications" are used interchangeably with DispatchEvent.
// Unlike web APIs, developers can check event.DefaultPrevented() after return, we don't return any data.
//
// Other frameworks:
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent
//
// Raise(event E) (err error_p.Error)
DispatchEvent(event E) (err error_p.Error)

// EventListeners() []EventListener[E] // Due to security problem, can't expose listeners to others

// Target_State
}

type Target_State interface {
AcceptSyncListener() bool
}

// EventListener Usually implement on some kind of services that:
Expand All @@ -45,19 +49,18 @@ type Target_State interface {
type EventListener[E Event] interface {
// It CAN be Blocking(Synchronous) & Non-Blocking, means It CAN block the caller in any ways.
// **Strongly suggest just use blocking if you force by strong logic requirements like authorization**
// if Cancelable() is `false`, Callee MUST NOT block caller. Linter MUST check this condition.
EventHandler(event E)

//
// EventListener can implement some functionality like:::
//

// It will part of process and can change the flow of the desire event.
// Some consideration:
// - Target can prevent in `AddEventListener` to register sync listener.
// - May be `Event` dispatcher don't implement `Event.DefaultPrevented()` and not let you to change the flow.
// - Just if `Event.Cancelable()`` is `true`, listener can change the flow.
Synchronous() bool

//
// EventListener can implement some functionality like:::
//
// Synchronous() bool

// - AddEventListener: Capture indicating that events of this type will be dispatched to the registered listener
// before being dispatched to any Target beneath it in the target tree.
Expand Down
32 changes: 12 additions & 20 deletions event/protocol/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,25 @@ package event_p

import (
datatype_p "memar/datatype/protocol"
error_p "memar/error/protocol"
logic_p "memar/math/logic/protocol"
time_p "memar/time/protocol"
)

// Event usually can be any other domain records that store in storage layer.
// Events CAN be any data-type in any domain.
// Event are runtime data-types that DON't need to store in storage layer.
//
// Events dispatch after base logic that make this Event.
// e.g. When a service request want to serve, a handler receive the request and decide to save the request for auditing
// after validate request codec and save request, a related event dispatch.
// This service can provide some mechanism to change the flow of request processing
//
// Other frameworks:
// https://www.w3.org/TR/DOM-Level-3-Events/#event-flow
// https://developer.mozilla.org/en-US/docs/Web/API/Event
// https://developer.mozilla.org/en-US/docs/Web/Events
// https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.eventdescriptor
type Event interface {
datatype_p.Field_DataType
time_p.Field_Time

Event_State
Event_Methods
}

type Event_State interface {
// Returns true or false depending on how event was initialized. Its return value does not always carry meaning,
// but true can indicate that part of the operation during which event was dispatched, can be canceled by invoking the preventDefault() method.
// It also means subscribers receive events in asynchronous or synchronous manner. true means synchronous manner.
Cancelable() bool
// Returns true if preventDefault() was invoked successfully to indicate cancellation, and false otherwise.
DefaultPrevented() bool
}

type Event_Methods interface {
// If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false,
// signals to the operation that caused event to be dispatched that it needs to be canceled.
PreventDefault() (err error_p.Error)
logic_p.Equivalence[Event]
}
12 changes: 2 additions & 10 deletions event/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@ import (

// Target dispatch events to listeners on desire event_p.EventMainType types.
type Target[E event_p.Event] struct {
acceptSyncListener bool

sync sync.Mutex
ls []event_p.EventListener[E]
}

//memar:impl memar/computer/language/object/protocol.LifeCycle
func (self *Target[E]) Init(acceptSyncListener bool) (err error_p.Error) {
self.acceptSyncListener = acceptSyncListener
//memar:impl memar/computer/capsule/protocol.LifeCycle
func (self *Target[E]) Init() (err error_p.Error) {
self.ls = make([]event_p.EventListener[E], 0, CNF_InitialListenersLength)
return
}
Expand All @@ -37,11 +34,6 @@ func (self *Target[E]) DispatchEvent(event E) (err error_p.Error) {
return
}
func (self *Target[E]) AddEventListener(callback event_p.EventListener[E]) (err error_p.Error) {
if callback.Synchronous() == true && self.acceptSyncListener == false {
// err =
return
}

self.sync.Lock()
var dls = self.ls
dls = append(dls, callback)
Expand Down

0 comments on commit 2cce432

Please sign in to comment.