# Events in Akash * A seperate `Event` struct is created which consists of type, module, action and attributes of event. And also created `BaseModuleEvent` struct which is used mainly for storing context of event. There is one more struct named `ModuleEvent` which is used to convert event to `SDKEvent`. Please check [this file](https://github.com/ovrclk/akash/blob/master/sdkutil/event.go#L42) for more info. * We create custom events using above structs and emit them when needed. For example: ``` type EventDeploymentCreated struct { Context sdkutil.BaseModuleEvent `json:"context"` ID DeploymentID `json:"id"` Version []byte `json:"version"` } // NewEventDeploymentCreated initializes creation event. func NewEventDeploymentCreated(id DeploymentID, version []byte) EventDeploymentCreated { return EventDeploymentCreated{ Context: sdkutil.BaseModuleEvent{ Module: ModuleName, Action: evActionDeploymentCreated, }, ID: id, Version: version, } } // ToSDKEvent method creates new sdk event for EventDeploymentCreated struct func (ev EventDeploymentCreated) ToSDKEvent() sdk.Event { version := encodeHex(ev.Version) return sdk.NewEvent(sdkutil.EventTypeMessage, append([]sdk.Attribute{ sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName), sdk.NewAttribute(sdk.AttributeKeyAction, evActionDeploymentCreated), sdk.NewAttribute(evVersionKey, string(version)), }, DeploymentIDEVAttributes(ev.ID)...)..., ) } ``` Here `EventDeploymentCreated` is an event created using above structs and will emit this event when deployment is created. Please check [this file](https://github.com/ovrclk/akash/blob/master/x/deployment/types/event.go) for more info on creating custom events. * In akash, event is usually emitted using `ctx.EventManager()` in keeper after updating store. ### Why events are emitted and what is the use of it? In akash, there is a command to listen `events` when emitted. Let me explain how it works: * A `bus` interface is created in akash which runs forever when started. It is generally a type of gatekeeper to handle publish and subscription of channnels. So, bus is initialized and subscribed to it in event cmd. * Next we use a goroutine to publish all the events which come from `EventsClient` of tendermint rpc client by subscribing to it. And before publishing those events, we parse those events and check whether those are from our modules. And if so, we publish them internally. For example, deployment events are parsed based on `Action` like this: ``` // ParseEvent parses event and returns details of event and error if occurred func ParseEvent(ev sdkutil.Event) (sdkutil.ModuleEvent, error) { if ev.Type != sdkutil.EventTypeMessage { return nil, sdkutil.ErrUnknownType } if ev.Module != ModuleName { return nil, sdkutil.ErrUnknownModule } switch ev.Action { case evActionDeploymentCreated: did, err := ParseEVDeploymentID(ev.Attributes) if err != nil { return nil, err } ver, err := ParseEVDeploymentVersion(ev.Attributes) if err != nil { return nil, err } return NewEventDeploymentCreated(did, ver), nil case evActionDeploymentUpdated: did, err := ParseEVDeploymentID(ev.Attributes) if err != nil { return nil, err } ver, err := ParseEVDeploymentVersion(ev.Attributes) if err != nil { return nil, err } return NewEventDeploymentUpdated(did, ver), nil case evActionDeploymentClosed: did, err := ParseEVDeploymentID(ev.Attributes) if err != nil { return nil, err } return NewEventDeploymentClosed(did), nil case evActionGroupClosed: gid, err := ParseEVGroupID(ev.Attributes) if err != nil { return nil, err } return NewEventGroupClosed(gid), nil default: return nil, sdkutil.ErrUnknownAction } } ``` * And in the same `event` cmd, we have a subscriber to handle all events published by above bus and print out them. For more info, please check [this `event cmd` code](https://github.com/ovrclk/akash/blob/master/events/cmd/root.go#L37)