EVA ICS core refractoring and async functions

When we started development of EVA ICS, asynchronous programming just started to be popular. EVA ICS 3 core is thread-based. It works pretty well, doesn’t produce too much memory/CPU load, but it can work even better.

Let me introduce atasker library. This is free, open source Python library, which will solve many problems as in EVA ICS core, as in any other similar project.

atasker library is still in pre-ALPHA stage, first stable version will be released together with new refractord EVA ICS core (scheduled – Q1 2020 but hope earlier, this year).

So, what is atasker library and how can it help?

Single supervisor for both threads, multiprocessing and coroutines

Want to run function in background? Just write a single command and it’s started

# in thread pool
background_task(func)()
# in multiprocessing pool
background_task(func, tt=TT_MP)()

Pools are managed by task supervisor, tasks are sorted by priorities so you can be 100% sure no more than allowed threads or multiprocessing tasks are running at the same time.

Workers

Worker is an object which runs specified function (executor) in a loop while active. How many times you’ve developed it? Dozens! In EVA ICS there’s about 30 different workers for different tasks. In atasker library, we’ve tried to include all common types of workers:

  • Background worker – just run function in a continuous loop
  • Background interval worker – run function with the specified interval or delay
  • Background queue worker – run function when there’s new task in internal worker’s queue
  • Background event worker – run function on external event

In atasker worker has asynchronous loop, while executor can be either synchronous (run in a thread), synchronous and static (run in a multiprocessing pool) or asynchronous (run with await). Worker automatically detects executor type, all you need is just to write an executor function:

@background_worker(interval=1)
def func(**kwargs):
  print('I run every second!')
func.start()
# ...
func.stop()

or simple custom worker class:

class MyWorker(BackgroundIntervalWorker)
  def run(self, **kwargs):
    print('I run every second too!')
worker = MyWorker(interval=1)
worker.start()

With atasker library background tasks and workers are real fun. Executor type auto-detection breaks PEP 20 a little bit (Explicit is better than implicit). But, on the other hand, simple is better than complex )