Session: Subscribing to Session Events

  • Events allow users to perform custom actions in response to operations made in a Document Store or a Session.

  • An event is invoked when the selected action is executed on an entity, or querying is performed.

  • Subscribing to an event in a Session is valid only for this session.

  • Subscribing to an event at the DocumentStore level subscribes to this event in all subsequent sessions.
    Read more about DocumentStore events here.

OnBeforeStore

This event is invoked as a part of saveChanges() but before it is actually sent to the server.
It should be defined with this signature:

store.addSessionListener("beforeStore", event => onBeforeStore(event));

The usage of SessionBeforeStoreEventArgs:

const beforeStoreEventArgs = new SessionBeforeStoreEventArgs(session, documentId, entity);

Example

Say we want to discontinue all of the products that are not in stock.

function onBeforeStore(args) {
    if (args.getEntity() instanceof Product) {
        const product = args.getEntity();
        if (product.unitsInStock === 0) {
            product.discontinued = true;
        }
    }
}

After we subscribe to the event, every stored entity will invoke the method.

store.addSessionListener("beforeStore", event => onBeforeStore(event));

session = store.openSession();
await session.store(new Product(
    {
        name: "RavenDB v3.5",
        unitsInStock: 0
    })
)

await session.store(new Product(
    {
        name: "RavenDB v4.0",
        unitsInStock: 1000
    })
)

await session.saveChanges(); // Here the method is invoked

OnBeforeDelete

This event is invoked by delete(id) or delete(entity). It is only executed when saveChanges() is called, but before the commands are actually sent to the server.
It should be defined with this signature:

store.addSessionListener("beforeDelete", event => onBeforeDelete(event));

The usage of SessionBeforeDeleteEventArgs:

const beforeDeleteEventArgs = new SessionBeforeDeleteEventArgs(session, documentId, entity);

Example

To prevent anyone from deleting entities we can create a method as follows:

function onBeforeDelete(args) {
    throw new Error("Not implemented");
}

and subscribe it to the session:

store.addSessionListener("beforeDelete", event => onBeforeDelete(event));

session = store.openSession();
let product = await session.load("products/1-A", Product);
let product2 = await session.load("products/2-A", Product);

// onBeforeDelete is triggered whether you
// call delete() on an entity or on its ID
await session.delete(product);
await session.saveChanges(); // NotSupportedException will be thrown

await session.delete("products/2-A");
await session.saveChanges(); // NotSupportedException will be thrown

OnAfterSaveChanges

This event is invoked after the saveChanges is returned.
It should be defined with this signature:

store.addSessionListener("afterSave", event => onAfterSaveChanges(event));

The usage of SessionAfterSaveChangesEventArgs:

const afterSaveChangesEventArgs = new SessionAfterSaveChangesEventArgs(session, documentId, entity);

Example

If we want to log each entity that was saved, we can create a method as follows:

function onAfterSaveChanges(args) {
    console.log("Document " + args.documentId + " was saved.");
}

OnBeforeQuery

This event is invoked just before the query is sent to the server. It should be defined with this signature:

store.addSessionListener("beforeQuery", event => onBeforeQuery(event));

The usage of SessionBeforeQueryEventArgs:

const beforeQueryEventArgs = new SessionBeforeQueryEventArgs(session, documentId, entity);

Example I

If you want to disable caching of all query results, you can implement the method as follows:

function onBeforeQuery(args) {
    args.queryCustomization.noCaching();
}

Example II

If you want each query to wait for non-stale results you can create an event as follows:

function onBeforeQuery(args) {
    args.queryCustomization.waitForNonStaleResults(30);
}

OnBeforeConversionToDocument

This event is invoked before conversion of an entity to blittable JSON document. E.g. it's called when sending a document to a server.
It should be defined with this signature:

store.addSessionListener("beforeConversionToDocument", event => onBeforeConversionToDocument(event));

The usage of BeforeConversionToDocumentEventArgs:

const beforeConversionToDocumentEventArgs = new BeforeConversionToDocumentEventArgs(session, documentId, entity);

Example

function onBeforeConversionToDocument(args) {
    if (args.getEntity() instanceof Product) {
        const product = args.getEntity();
        product.before = true;
    }
}

OnAfterConversionToDocument

This event is invoked after conversion of an entity to blittable JSON document.
It should be defined with this signature:

store.addSessionListener("afterConversionToDocument", event => onAfterConversionToDocument(event));

The class AfterConversionToDocumentEventArgs:

const afterConversionToDocument = new AfterConversionToDocumentEventArgs(session, documentId, entity, document);

Example

function onAfterConversionToDocument(args) {
    if (args.getEntity() instanceof Product) {
        const product = args.getEntity();
        if (product.document.after == null) {
            product.document.after = true;
        }
    }
}

OnBeforeConversionToEntity

This event is invoked before conversion of a JSON document to an entity. E.g. it's called when loading a document.

It takes the argument BeforeConversionToEntityEventArgs, that consists of a JSON document, its ID and type, and the session instance.

store.addSessionListener("beforeConversionToEntity", (event: BeforeConversionToEntityEventArgs) => {
    const document = ObjectUtil.clone(event.document);

    document.before = true;
    event.document = document;
});

OnAfterConversionToEntity

This event is invoked after conversion of a JSON document to an entity. It takes the argument AfterConversionToEntityEventArgs, that consists of a JSON document, its ID, the session instance and a converted entity.

store.addSessionListener("afterConversionToEntity", (event: AfterConversionToEntityEventArgs) => {
    if (event.entity instanceof Item) {
        const item = event.entity;
        item.after = true;
    }
});