EventStore-Client-NodeJS icon indicating copy to clipboard operation
EventStore-Client-NodeJS copied to clipboard

`emitEnabled` only available on projection update, not on create

Open TheFlow0360 opened this issue 3 years ago • 2 comments

When creating a projection, the available options look like this:

export interface CreateProjectionOptions extends BaseOptions {
    /**
     * Enables tracking emitted streams.
     * @default false
     */
    trackEmittedStreams?: boolean;
}

When updating, this is different:

export interface UpdateProjectionOptions extends BaseOptions {
    /**
     * Enables emitting events from the projection.
     * Passing `undefined` will leave emitEnabled at its current value.
     * @default undefined
     */
    emitEnabled?: boolean;
}

Because of that, I need to create and instantly modify a projection, if I want it to be able to emit events. I haven't actually tested it, but I can imagine this being even more problematic in case there are already events in the stream consumed by the projection, as the create immediatly activates the projection which consequently runs into an error as soon as it's trying to emit the first event.

It would be better, if the options for create and update match, or at least (if trackEmittedStreams can't be updated) that emitEnabled becomes part of the CreateProjectionOptions.

TheFlow0360 avatar Aug 01 '22 15:08 TheFlow0360

Hi Florian,

This is due to it being missing on the server side, but the fix should be in the upcoming 22.6, so it can be added to the client with a polyfill for earlier server versions.

The issue tracking the final piece of work is here: https://github.com/EventStore/EventStore/issues/3410

Because of that, I need to create and instantly modify a projection, if I want it to be able to emit events. I haven't actually tested it, but I can imagine this being even more problematic in case there are already events in the stream consumed by the projection, as the create immediatly activates the projection which consequently runs into an error as soon as it's trying to emit the first event.

If you want to be unblocked, and depending on how you feel about using internal / undocumented apis, you could temporarily add the polyfill yourself:

Something like:

import { BaseOptions, EventStoreDBClient } from "@eventstore/db-client";

export interface CreateProjectionHTTPOptions extends BaseOptions {
  /**
   * Enables tracking emitted streams.
   * @default false
   */
  trackEmittedStreams?: boolean;
  /**
   * Enables emitting events from the projection.
   * @default false
   */
  emitEnabled?: boolean;
}

const createProjectionHTTP = async function (
  this: EventStoreDBClient,
  projectionName: string,
  query: string,
  {
    emitEnabled = false,
    trackEmittedStreams = false,
    ...baseOptions
  }: CreateProjectionHTTPOptions = {}
) {
  await this.HTTPRequest(
    "POST",
    `/projections/continuous`,
    {
      ...baseOptions,
      searchParams: {
        name: projectionName,
        emit: emitEnabled.toString(),
        trackemittedstreams: trackEmittedStreams.toString(),
      },
    },
    query
  );
};

Which you can then call as:

import { EventStoreDBClient } from "@eventstore/db-client";

const client = EventStoreDBClient.connectionString`esdb+discover://admin:changeit@${CLOUD_ID}.mesdb.eventstore.cloud`;

const PROJECTION_NAME = "count events";
const EVENT_TYPE = "count_this";
const STREAM_NAME = "some_stream_name";
const projection = `
fromStream("${STREAM_NAME}")
.when({
  $init() {
    return 0;
  },
  ${EVENT_TYPE}(state, event) {
    return state + 1
  }
});
`;

await createProjectionHTTP.call(client, PROJECTION_NAME, projection, {
  emitEnabled: true,
  trackEmittedStreams: true,
});

Obviously, this.HTTPRequest is internal, so don't depend on it not to change / disappear between minor versions etc. Also, this isn't tested, so make sure it actually does what you expect it to, but this is likely what the internal fallback will look like.


I'll use this issue to track the adding of the option, so you'll be notified when it's added / released.

George-Payne avatar Aug 02 '22 10:08 George-Payne

Thanks a lot for the extensive information! Right now I'm just protoyping some stuff to evaluate the use of EventStore DB, if we decide to actually use it we'll see if the fix is already released.

TheFlow0360 avatar Aug 02 '22 11:08 TheFlow0360