How to access a newly created entity? #882
-
There is a common scenario: |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Then I found |
Beta Was this translation helpful? Give feedback.
-
Hey, thanks for reporting, discussing these things are super important for us to figure out the best UX 😄 Still, you should not rely on the entity itself as the source of truth, but rather on the events. You cannot access entities (well, you can with the In fact, even if that The reason is that entities are in some middle ground between the write (commands) and the read (read models) parts of the framework and are mainly used for snapshotting and relative ordering of events. Events are a way of defining that stuff has happened in your app (facts), entities then use them to generate the state they hold. Let's see how we can integrate this knowledge into your example. I'm gonna be separating by use cases. Creating a room and joiningIf your chat app lets users join the rooms instantly after creation, you can either create a public handle(command: TCommand, register: Register): Promise<void> {
// some logic
const roomId = UUID.generate()
register.events(new RoomWithParticipantCreated(roomId, command.userId, /* more parameters */))
// or
register.events(new RoomCreated(roomId), new RoomJoined(roomId, command.userId))
} With this, we could write an entity for the room that has the participant inside already: @Entity
export class Room {
public constructor(public id: UUID, readonly participants: Array<UUID>) {}
@Reduces(RoomCreated)
public static reduceRoomCreated(event: RoomCreated): Room {
return new Room(event.roomId, [])
}
@Reduces(RoomJoined)
public static reduceRoomJoined(event: RoomCreated, entity?: Room): Room {
if (!entity) throw new Error(`Room with event ${event.roomId} not found`)
return new Room(entity.id, [...entity.participants, event.userId])
}
} Letting the user know which room they participate inGiven that this is a different piece of data, we'd have to create a new entity called @EventHandler(RoomJoined)
export class MyRoomsUpdater {
public static async handle(
event: RoomJoined,
register: Register
): Promise<void> {
register.events(new MyRoomsUpdated(event.roomId, event.userId))
}
} And then the entity: @Entity
export class MyRooms {
public constructor(public id: UUID, readonly rooms: Array<UUID>) {}
@Reduces(MyRoomsUpdated)
public static reduceMyRoomsUpdated(event: MyRoomsUpdated, entity?: MyRooms): MyRooms {
const rooms = entity?.rooms ?? []
return new MyRooms(event.userId, [rooms, event.roomId])
}
} This way you could then access it from a Why so much hassleOne of the Booster goals is to provide an efficient way to create apps that support high throughput situations without making the developer have to think in these restrictions. In order to achieve this, some constraints have to be set, and we are constantly working to figure out how to ease these constraints and make the UX much better. So, again, thanks for reporting, I hope that this has been useful in some way 😄 PS: Moving this to a discussion, as it is much more appropriate there |
Beta Was this translation helpful? Give feedback.
Hey, thanks for reporting, discussing these things are super important for us to figure out the best UX 😄
Still, you should not rely on the entity itself as the source of truth, but rather on the events. You cannot access entities (well, you can with the
Booster.entity
function, but generally you don't want that) and rather you would access read models if you wanted to access the state of your system.In fact, even if that
TODO
returned something, an entity ID wouldn't be in that response 😅The reason is that entities are in some middle ground between the write (commands) and the read (read models) parts of the framework and are mainly used for snapshotting and relative ordering of events.
…