Skip to content

Race condition in FormBuilderService causing incorrect fields in form #5101

@autavares-dev

Description

@autavares-dev

Describe the bug

We have been receiving sporadic user complaints about the submission form loading inappropriate fields for the type being submitted. Our DSpace installation supports multiple submission types, and we rely heavily on <type-bind> in the backend configuration.

After investigation, the problem appears to originate in form-builder.service.ts, specifically in the getTypeField method. This method calls setTypeBindFieldFromConfig to retrieve the configured metadata field via a REST request. However, the method sometimes returns before the request has completed, which causes the error to occur intermittently (race-condition).

To Reproduce

To reproduce the issue more consistently, I have found that adding an artificial delay in the pipe of setTypeBindFieldFromConfig works.

 setTypeBindFieldFromConfig(): void {
    this.configService.findByPropertyName('submit.type-bind.field').pipe(
      getFirstCompletedRemoteData(),
      delay(5000),
    ).subscribe((remoteData: any) => {
  // ...

Steps to reproduce the behavior:

  1. In the backend, configure a field with only for type A and another for type B.
  2. In the frontend, add a high delay (5s or more) to increase the likelihood of the error.
  3. Start two submissions in the frontend: one of type A and one of type B.
  4. Return to the submissions page and refresh with Ctrl+F5 (to clear the cache for the setTypeBindFieldFromConfig request).
  5. Edit one of the submissions (sometimes the incorrect fields are already present here).
  6. Go back to the submissions page and edit the other submission.
  7. Navigate back again and repeat — the incorrect fields appear intermittently.

When the problem manifests, I believe getTypeField is returning undefined and causing the wrong fields to be added to the form.

I have found that his small change below fixes the problem. However, if the DSpace installation is using other field rather than dc.type, the problem would persist.

getTypeField(): string {
    if (hasNoValue(this.typeField)) {
      this.typeField = 'dc_type'; // Sets a default before calling async method
      if (hasValue(this.configService)) {
        this.setTypeBindFieldFromConfig();
      }
    }
    return this.typeField;
 }

I have not been able to find a definitive fix for the problem.

I attempted to change getTypeField to return an Observable<string>, but this would affect modelFromConfiguration and its consumers, making it a non-trivial change.

Expected behavior

When calling getTypeField the method should return the current value if present or wait for setTypeBindFieldFromConfig to get the correct value before returning.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    📋 To Do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions