Skip to content

Conversation

@espy
Copy link

@espy espy commented Dec 7, 2021

Quick first implementation in line with apache#8422.

Covered long-running tasks:

  • database compaction
  • single replication
  • continuous replication
  • view indexing
  • find indexing (via view indexing/abstract-mapreduce when not using the indexeddb adapter)
    • the indexeddb adapter brings its own find indexing/querying implementation based on native IDB indexes, which don't support precise progress monitoring

Tests

Run tests for this feature:
$ GREP="active_tasks" && npm test

Demo

We've built a demo application for trying out (and visualizing) the activeTasks API for monitoring long-running tasks: https://github.com/neighbourhoodie/pouchdb-activetasks-demo

Real-time logging

Real-time logging of activeTasks via Proxies

At the top of the <script> tag in the file above, add:

  PouchDB.activeTasks.add = new Proxy(PouchDB.activeTasks.add, {
    apply: (target, thisArg, argumentsList) => {
      const task = argumentsList[0]
      console.log(`➕ Added Task "${task.name}" with ${task.total_items} total items`)
      return Reflect.apply(target, PouchDB.activeTasks, argumentsList);
    }
  })

  PouchDB.activeTasks.update = new Proxy(PouchDB.activeTasks.update, {
    apply: (target, thisArg, argumentsList) => {
      const task = PouchDB.activeTasks.get(argumentsList[0])
      if (!task) return
      const durationInMilliseconds = new Date().getTime() - new Date(task.createdAt).getTime()
      console.log(`🖌️ Updated Task "${task.name}" (${task.id}) with ${argumentsList[1].completed_items}/${argumentsList[1].total_items || task.total_items} items after ${durationInMilliseconds / 1000} seconds`)
      return Reflect.apply(target, PouchDB.activeTasks, argumentsList);
    }
  })

  PouchDB.activeTasks.remove = new Proxy(PouchDB.activeTasks.remove, {
    apply: (target, thisArg, argumentsList) => {
      const task = PouchDB.activeTasks.get(argumentsList[0])
      if (!task) return
      const durationInMilliseconds = new Date(task.updatedAt).getTime() - new Date(task.createdAt).getTime()
      console.log(`✅ Removed/Completed Task "${task.name}" (${task.id}) with ${task.completed_items}/${task.total_items} items after ${durationInMilliseconds / 1000} seconds`)
      return Reflect.apply(target, PouchDB.activeTasks, argumentsList);
    }
  })

This traps the method calls, runs console logs and then the original target methods. It can be extended to become an event emitter or whatever.

return this.tasks;
};

ActiveTasks.prototype.add = function (task) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API naming nitpick, pairing add with get feels a bit off to me, how about create maybe.

I have no super strong feelings about this, or research to back this up, but add conveys to me “append to an existing list” which is an implementation detail from behind the API, whereas create conveys more “I need a new task” from the user-side of the API.

There is probably an equally strong linguistic argument for going the other way around, so the is more taste than a required change.

One thing that would be nice, but doesn’t quite fit would be to mirror the PouchDB API for doc, but that mirrors the HTTP verbs used by CouchDB and I think that is taking it a little too far (we’d use .post() to update.

@snvfk1n snvfk1n force-pushed the feat/active-tasks branch 2 times, most recently from 4a95fae to 887ee4a Compare January 3, 2022 13:37
@snvfk1n snvfk1n force-pushed the feat/active-tasks branch 3 times, most recently from 5ff2d89 to c76d531 Compare January 11, 2022 16:24
@snvfk1n snvfk1n force-pushed the feat/active-tasks branch 3 times, most recently from 7dad3a4 to 7d2f323 Compare January 19, 2022 16:12

var task = src.activeTasks.get(taskId);
if (task) {
src.info().then(function (info) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might there a different way of updating total_items here for continuous replication other than regularly fetching the database info? we've had a bug where this callback ran into an error due to currentBatch being set to undefined—it was clearly defined before src.info() was called, so this happened in the meantime.

@snvfk1n snvfk1n force-pushed the feat/active-tasks branch from 8c9daed to 58fc42b Compare April 20, 2022 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants