# Event Bus

Like many other programming languages, Vortex will cache module imports, meaning that files get evaluated only once on the first import, and the cached version will be returned on every consecutive import after that.

This allows us to instantiate a single object that can be imported and modified throughout the entire application.

## Event Type

We'll begin by defining an `Event` type that the event bus can accept:

{% code title="event\_bus.vtx" overflow="wrap" %}

```rust
type Event = (name) => ({
    name: name
})
```

{% endcode %}

It's pretty bare bones, but we'll use it to make sure that only valid events are passed to the event bus.

### Event Bus

We'll now define the event bus constructor:

{% code title="bus/event\_bus.vtx" overflow="wrap" %}

```rust
type EventBus = () => ({
    events: {},
    addEvent: (e) => {
        if (e.info().typename != "Event") {
            println(f"${e} is not a valid Event")
            return
        }

        if (this.events[e.name]) {
            println(f"Event ${e} is already defined")
            return
        }

        this.events[e.name] = {
            event: e,
            subscribers: []
        }
    },
    removeEvent: (event_name) => {
        this.events.remove_prop(event_name)
    },
    subscribe: (event_name, callback) => {
        if (!this.events[event_name]) {
            println(f"No such event \"${event_name}\"")
            return
        }

        this.events[event_name].subscribers.append(callback)
    },
    unsubscribe: (event_name, callback) => {
        if (!this.events[event_name]) {
            println(f"No such event \"${event_name}\"")
            return
        }

        for (this.events[event_name].subscribers, index, sub) {
            if (sub == callback) {
                this.events[event_name].subscribers.remove(index)
                break
            }
        }
    },
    emit: (event_name, payload = None) => {
        if (!this.events[event_name]) {
            println(f"No such event \"${event_name}\"")
            return
        }

        const e = this.events[event_name]
        for (e.subscribers, index, sub) {
            if (sub.info().arity == 0) {
                sub()
            } else {
                sub(payload)
            }
        }
    }
})
```

{% endcode %}

The event bus will need to have the ability to store events and their subscribers (really, just callbacks), add new events, remove events, subscribe and unsubscribe callbacks to events and emit events.

Just to make things nice and concise, we'll declare an EventType object that we'll use when subscribing/unsubscribing to events:

{% code title="bus/event\_bus.vtx" overflow="wrap" %}

```rust
var EventType = {
    Funds_Added: "funds_added",
    Funds_Removed: "funds_removed"
}
```

{% endcode %}

Next, we instantiate a global event bus that will be used throughout the entire application, and add two new events to it based on the `EventType` we just declared:

{% code title="bus/event\_bus.vtx" overflow="wrap" %}

```rust
const event_bus = EventBus()

event_bus.addEvent(Event(EventType.Funds_Added))
event_bus.addEvent(Event(EventType.Funds_Removed))
```

{% endcode %}

That's it, we now have an event bus that we can import in other parts of our application. This event bus has two events that can be subscribed to and emitted. Let's explore an example of that.

In another nested file, we'll import the event\_bus and add a new event to it.

We'll also create some callbacks to handle the events and subscribe to them. This is all that this file will do, we'll handle emitting the events in another file.

{% code title="bus/src/nested/other.vtx" overflow="wrap" %}

```rust
import [event_bus, EventType, Event] : "../../event_bus"

EventType.Account_Deleted = "account_deleted"
event_bus.addEvent(Event(EventType.Account_Deleted))

var balance = 55.5

const handle_account_deleted = (payload) => {
    println("OH NOOOOO")
}

const handle_funds_added = (payload) => {
    balance += payload.amount
    println(balance)
}

const handle_funds_removed = (payload) => {
    balance -= payload.amount
    println(balance)
}

event_bus.subscribe(EventType.Funds_Added, handle_funds_added)
event_bus.subscribe(EventType.Funds_Removed, handle_funds_removed)
event_bus.subscribe(EventType.Account_Deleted, handle_account_deleted)
```

{% endcode %}

In our main file, we'll also import the `other` file we just wrote. This will evaluate it, and add the new event to the bus, as well as handle the subscriptions. We'll then import the same `event_bus` and emit those events:

{% code title="bus/src/main.vtx" overflow="wrap" %}

```rust
import other : "nested/other"
import [event_bus, EventType] : "../event_bus"

event_bus.emit(EventType.Funds_Added, { amount: 20 })
event_bus.emit(EventType.Funds_Removed, { amount: 13.46 })
event_bus.emit(EventType.Account_Deleted)
```

{% endcode %}

This should then go through the list of callbacks and fire them off, producing this output:

```
75.5
62.04
OH NOOOOO
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dibs.gitbook.io/vortex-docs/examples/event-bus.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
