resolve
resolve copied to clipboard
Custom-read-model-connector projection handlers are not called in a new application
Describe the bug
When creating a new application with the npx create-resolve-app
command, custom-read-model-connector projection handlers are never called. This occurs with and without a template. It occurs with a custom-read-model-connector I built, and one that is present in the hacker-news example.
To Reproduce
- Create a new application with the hacker-news template
npx create-resolve-app hacker-news-custom-read-model-connector -e hacker-news -t
- In
common/read-models/search.projection.ts
, add aconsole.log('STORY_CREATED event received in search.projection.ts')
statement to theSTORY_CREATED
projection handler. -
npm run dev
- A window should be opened in your browser with the hacker-news app running. Click "login" and create a new account.
- Click "submit" and create a new story.
- Note that the console.log statement you created above in step 2 never printed.
Expected behavior
Following the steps above, step 6 prints the console.log statement in the search projection handler STORY_CREATED
Desktop (please complete the following information):
- OS: iOS
- Browser: Chrome but it is replicable in Postman too
- Node.js Version: 16.13.2
- ReSolve Version: 0.34.3
Additional context
I did quite a bit of debugging in the source code and the ending issue seems to be in runtime-base/lib/custom-read-model.js
. The build
function is called multiple times for the Search event subscriber. The first time, the events are retrieved from eventstoreAdapter.loadEvents
as null and status.busy
is set to false
as expected. Then, however, the busy
function is rerun and the eventstoreAdapter.loadEvents
call returns events as an empty array, []
. This results in returning an object where continue: false
without updating status.busy
to false
.. When continue
equals false
, the execution reaches an empty if block with the comment, TODO: ???
in node_modules/@resolve-js/runtime-base/lib/notification-next.js
.
This results in any subsequent real event, like STORY_CREATED
, to be unhandled because the build
function returns early because status.busy
is true
on line ~66: if (status == null || status.status !== 'deliver' || !!status.busy)
.
When the event array is returned empty, as described above, I can update the subscribers database to set busy
to false
and this seems to fix the issue, but I don't know what side effects this has and I don't know if it's addressing the underlying issue that an empty array of events is returned. I think the issue is one of two things: the build function should have never been called when there were no new events, or the busy status was never updated in the case when events.length
is 0. If the latter is the case, the bottom code change seems to fix the immediate issue around line 130:
} else if (events.length === 0) {
// start potential bug fix
await eventstoreAdapter.ensureEventSubscriber({
applicationName,
eventSubscriber,
status: { ...status,
busy: false
},
updateOnly: true
});
// end potential bug fix
return {
type: 'build-direct-invoke',
payload: {
continue: false
}
};
} else if (events.length > 0) {