Status Desktop client made in Nim & QML https://status.app
Go to file
Eric Mastro 66912fd811 feat: introduce Task Manager threadpool
The `TaskManager` threadpool is a memory-safe replacement for the `spawnAndSend` operations that are currently causing memory issues in status-desktop.

From a fundamental memory management point of view, `libstatus/settings`, `libstatus/contracts`, and `libstatus/tokens` (custom tokens) have all been converted to `{.threadvar.}`s and `Atomic[bool]`s to maintain the cache and `dirty` flag across threads, respectively, eliminating the need for thread locks and incorrect `{.gcsafe.}` compiler overrides.

The successful [recyclable threadpool experiment from `nim-task-runner`](https://github.com/status-im/nim-task-runner/blob/test/use-cases/test/use_cases/test_sync.nim) using `AsyncChannel[ThreadSafeString]`s was brought over to `status-desktop` and implemented in somewhat of a hardcoded manner, as we knew this would save some time instead of trying to create a fully fleshed out `nim-task-runner` API and build a miraculous macro that may or may not be able to generate the needed API.

The threadpool is started by the `TaskManager` and both the `TaskManager` and the `TaskManager`'s threadpool are started as early as possible in the application lifecycle (in `nim_status_client.nim`). The `TaskManager` creates a thread to run the threadpool. During its initialization, the threadpool then spools up all the threads it will manage and puts them in an idle thread sequence. This is to prevent expensive thread creation and teardown happening during the app's lifetime as it is quite expensive and blocks the main thread. When tasks comes in to the pool, the task is sent to an idle thread, or put in a queue if all threads are busy. The idle thread is moved to the busy thread sequence. When a task is completed, the thread is taken out of the busy threads sequence and moved back in to the sequence of idle threads, effectively recycling it.

The first `spawnAndSend` we were able to change over to the new threadpool was `estimate`, which estimates the gas of a sticker purchase transaction.

From the consumer point of view, the existing `spawnAndSend` to achieve this looks like:
```nim
  proc estimate*(self: StickersView, packId: int, address: string, price: string, uuid: string) {.slot.} =
    let status_stickers = self.status.stickers
    spawnAndSend(self, "setGasEstimate") do:
      var success: bool
      var estimate = status_stickers.estimateGas(packId, address, price, success)
      if not success:
        estimate = 325000
      let result: tuple[estimate: int, uuid: string] = (estimate, uuid)
      Json.encode(result)
```
And the new syntax looks like this:
```nim
  proc estimate*(self: StickersView, packId: int, address: string, price: string, uuid: string) {.slot.} =
    self.status.taskManager.threadPool.stickers.stickerPackPurchaseGasEstimate(cast[pointer](self.vptr), "setGasEstimate", packId, address, price, uuid)
```
The logic inside the `spawnAndSend` body was moved to [src/status/tasks/stickers.nim](https://github.com/status-im/status-desktop/compare/experiment/tasks-3?expand=1#diff-09e57eef00b0cee5c4abdb9039f948d8372e7003e09e934a9b4c7e9167d47658).

This is just the first migration of `spawnAndSend`, however moving the majority of the remaining `spawnAndSend`s will likely just be an exercise in copy/pasta. There will be one or two that may require a bit more thinking, depending how they rely on data from the model.

Once the `spawnAndSend`s have been converted to the threadpool, we can start implementing the [long-running process from the task runner use case experiments](https://github.com/status-im/nim-task-runner/blob/test/use-cases/test/use_cases/test_long_running.nim).

And finally, we can then implement the [async tasks](https://github.com/status-im/nim-task-runner/blob/test/use-cases/test/use_cases/test_async.nim) if needed.

@michaelsbradleyjr and I spent many hours digging in to the depths of nim's memory management in an attempt to understand it. We have created [a presentation with our task runner experiment findings](https://docs.google.com/presentation/d/1ItCxAfsVTcIoH_E4bgvmHljhbU-tC3T6K2A6ahwAedk/edit?usp=sharing), and @michaelsbradleyjr has spent time [answering questions off the back of that presentation.](https://gist.github.com/michaelsbradleyjr/1eaa9937b3fbb4ffff3fb814f0dd82a9).

We have created a fork of `edn.nim` at `status-im/edn.nim` and we need the PR to be merged and the commit hash updated before we can merge this PR in to `status-desktop`.
2021-03-18 13:15:05 -04:00
ci refactor: embed Infura key at compile time 2020-12-09 12:10:12 -06:00
docs update screenshot 2021-03-11 16:39:11 -05:00
scripts chore: change translations to only translate complete languages 2021-02-18 15:23:58 -05:00
src feat: introduce Task Manager threadpool 2021-03-18 13:15:05 -04:00
ui refactor(Communities): make member list look as intended 2021-03-18 10:03:24 +01:00
vendor feat: introduce Task Manager threadpool 2021-03-18 13:15:05 -04:00
.gitignore feat: introduce Task Manager threadpool 2021-03-18 13:15:05 -04:00
.gitmodules feat: introduce Task Manager threadpool 2021-03-18 13:15:05 -04:00
.npmrc chore: refactor Linux and macOS build/packaging steps 2020-06-22 10:53:57 -05:00
.yarnrc chore: refactor Linux and macOS build/packaging steps 2020-06-22 10:53:57 -05:00
AppRun fix: set default language 2021-02-22 09:57:56 -05:00
Info.plist chore: revise how dev version of app icon is set on macOS during `make run` 2021-01-21 15:36:32 -06:00
Info.runner.plist chore: revise how dev version of app icon is set on macOS during `make run` 2021-01-21 15:36:32 -06:00
LICENSE.md docs: indicate MPL 2.0 as the license 2020-09-23 15:14:59 -04:00
Makefile chore: revise how dev version of app icon is set on macOS during `make run` 2021-01-21 15:36:32 -06:00
QtWebEngineProcess.plist chore: refactor Linux and macOS build/packaging steps 2020-06-22 10:53:57 -05:00
README.md move building section to docs section; use readme from docs/readme 2020-06-22 10:34:07 -04:00
build-linux.sh chore: refactor Linux and macOS build/packaging steps 2020-06-22 10:53:57 -05:00
config.nims build: dynamically link to status-go built as a shared library 2020-08-28 12:32:49 -04:00
docker-linux-app-image.sh fix: add jq to dockerfile 2020-11-06 16:22:07 -05:00
env.sh feat: get collectibles from the contracts and their respective apis 2020-06-18 10:55:48 -04:00
fleets.json update mailserver fleet port to 443; 30504 was causing issues for some people 2020-12-09 16:55:59 -05:00
nim-status.desktop change title from Nim Status Client to Status Desktop 2020-09-07 09:30:02 -04:00
nim.cfg build system refactoring 2020-06-08 13:07:25 -04:00
nim_status_client.nimble docs: indicate MPL 2.0 as the license 2020-09-23 15:14:59 -04:00
nim_status_client.sh chore: refactor Linux and macOS build/packaging steps 2020-06-22 10:53:57 -05:00
package-lock.json chore: bump package-lock.json 2021-01-25 16:04:13 -06:00
package.json fix: inside packaged macOS builds 'OPEN ME.webloc' should be a file not a symlink 2021-01-22 14:10:09 -05:00
status-dev.icns chore: revise how dev version of app icon is set on macOS during `make run` 2021-01-21 15:36:32 -06:00
status-dev.svg build: use a different colored app icon and a non-default STATUS_PORT for dev builds 2020-12-18 15:37:06 -05:00
status-macos-dev.svg chore: refactor prod/dev app icon and related logic for macOS 2021-01-15 19:12:42 -05:00
status-macos.svg chore: refactor prod/dev app icon and related logic for macOS 2021-01-15 19:12:42 -05:00
status.icns chore: revise how dev version of app icon is set on macOS during `make run` 2021-01-21 15:36:32 -06:00
status.ico add status icon 2020-05-11 16:41:45 -04:00
status.svg chore: update status.svg 2020-09-18 08:42:49 -05:00
windows-install.txt build: implement packaging steps for the Windows build 2020-07-17 13:57:32 -05:00

README.md