0

I have a notifications app which sends users notifications. It uses a .NET core backend, an angular frontend and Cosmos DB. Within this I have an API endpoint function which is linked to a button used to clean up inactive users' records from the DB based on a selected time period. This database job takes a long time to complete (up to 30 minutes) and is a problem because chrome's maximum time out limit is only 5 minutes. This prevents a "Success, users deleted" message from showing up on the client side. What strategy or workaround can I use to avoid this problem?

API Endpoint

        [HttpDelete("CleanUpInactiveUsers/{years}")]
        public async Task<IActionResult> CleanUpInactiveUsers(string years)
        {
            try
            {
                await Queries.RemoveInactiveUsers(years);
                return Ok($"Users inactive for more than {years} have been deleted");
            }
            catch (Exception ex)
            {
                return StatusCode((int)HttpStatusCode.InternalServerError);
            }
        }

Frontend call

// getUsersWithCondition(args) returns the total number of users if args="All", 
// otherwise return no. of users who haven't been active for more than args=<years>
// deleteInactiveUsers() linked with API endpoint snippet above.
.
.
.
            case this.TaskEnum.CleanInactiveUsers:{

              this._apiService.showToast(true, 'Clean Up of inactive users has begun. You will be notified once completed.');

              this._apiService.getUsersWithCondition(item.Params['time']).subscribe((response:string) =>
              {
                this.finalCount = Number(response);
              });

              this._apiService.deleteInactiveUsers(item.Params['time']).toPromise().then(res =>
                {
                    this._apiService.showToast(true, 'Deleted '+ this.finalCount + ' User(s)');
                }
              ).catch((error) => EpDialogService.error({message: 'In App Notification', description: `An error ocurred while executing the task ${ item.Task }`}));
              break;
            }
3

For such long-running tasks, delegate them to a background task.

Then you could have 2 API endpoints, one to start the long-running task and a second one to request its current status.

For example, your DELETE /CleanUpInactiveUsers/{years} invocation could return a redirect status code, redirecting the front-end to /CleanUpInactiveUsers/{years}/result if the deletion process is started successfully. The front-end could periodically do a GET /CleanUpInactiveUsers/{years}/result to check on the completion status of the task.

It would be a matter of agreement how long the .../result end-point would be valid after the task has completed.

2
  • I was just wondering if there was any way to prevent the periodic "polling" to the second status API. Is it possible to avoid the back-and-forth responses for a sole "push" strategy (keeping in mind of chrome's timeout)? I came across something called SignalR, but I'm not sure if it is appropriate for this use case. Apr 9 at 7:00
  • 1
    Yes, it is possible to prevent the periodic polling, using any technique for pushing data from the server to the client.The main point of my answer is to separate the starting of the action from being informed about the final result. Apr 9 at 9:13
0

Websockets could be used to prevent the timeout. Then you can even send updates during the work to the client, without the client have to constantly ask for changes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.