Remove Modes

It is complicated to remove documents with active relations. Sometime you might want to force remove a document, even if it has active relations, by ignoring the relations or by remove the related documents as well. DryerJS provides some modes to remove documents.

export enum RemoveMode {
  RequiredCleanRelations = 'RequiredCleanRelations',
  IgnoreRelations = 'IgnoreRelations',
  CleanUpRelationsAfterRemoved = 'CleanUpRelationsAfterRemoved',
}
  • RequiredCleanRelations: This is the default mode. It will throw an error if the document has active relations.
  • IgnoreRelations: It will remove the document even if it has active relations and leave related documents as they are.
  • CleanUpRelationsAfterRemoved: It will remove the document and also try to remove the related documents.

By default, only RequiredCleanRelations mode is enabled. To enabled other modes, you need to set the removalConfig in the @Definition decorator.

@Definition({
  removalConfig: {
    allowIgnoreRelationCheck: true,
    allowCleanUpRelationsAfterRemoved: true,
  },
})
export class Product {}

Error Handling

This is only for CleanUpRelationsAfterRemoved.

DryerJS will try to remove the related documents after the main document is removed with CleanUpRelationsAfterRemoved mode. The operation is not awaited with the main operation. Meaning that the main operation can be removed and respond as successful to the client but the related documents removal can fail. The most possible reason is some hooks for the related documents are throwing an error. You would want to response to the error. You can do that by providing a handler for the error.

import {
  AfterRemoveHookInput,
  FailCleanUpAfterRemoveHandler,
  FAIL_CLEAN_UP_AFTER_REMOVE_HANDLER,
} from 'dryerjs';
 
@Injectable()
class FailHandler implements FailCleanUpAfterRemoveHandler {
  async handleItem(
    input: AfterRemoveHookInput<any, any>,
    error: Error,
  ): Promise<void> {
    console.log('handleItem', input, error);
  }
 
  async handleAll(
    input: AfterRemoveHookInput<any, any>,
    error: Error,
  ): Promise<void> {
    console.log('handleAll', input, error);
  }
}
 
@Module({
  // other configs
  providers: [{
    provide: FAIL_CLEAN_UP_AFTER_REMOVE_HANDLER,
    useClass: FailHandler,
  }],
})
export class AppModule {}

DryerJS will be using the FailCleanUpAfterRemoveHandler in a loop, below psuedo code shows how it is used.

  private async cleanUpRelationsAfterRemoved(input: AfterRemoveHookInput) {
    try {
      for (const relatedDocument of relatedDocuments) {
        try {
          await relatedDocument.remove();
        } catch (error) {
          await this.errorHandler.handleItem(input, error);  
        }
      }
    } catch (error) {
      await this.errorHandler.handleAll(input, error);  
    }
  }

From that, if your handleItem method does not throw an error, the loop will continue to remove the next related document. If it throws an error, the loop will stop and the handleAll method will be called.

If you do not provide a handler, DryerJS will throw error when the related documents removal fails. Which will stop removing the chain of removing the related documents.

Detail implementation can be found here (opens in a new tab) on the #cleanUpRelationsAfterRemoved method.