<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mikael Koli</title>
    <description>The latest articles on DEV Community by Mikael Koli (@miksus).</description>
    <link>https://dev.to/miksus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F912800%2F7f584dec-cc7e-4ae6-aa72-56df246c6211.jpeg</url>
      <title>DEV Community: Mikael Koli</title>
      <link>https://dev.to/miksus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miksus"/>
    <language>en</language>
    <item>
      <title>New Horizon in Automation: Rocketry</title>
      <dc:creator>Mikael Koli</dc:creator>
      <pubDate>Tue, 23 Aug 2022 06:10:10 +0000</pubDate>
      <link>https://dev.to/miksus/new-horizon-in-automation-rocketry-2ni5</link>
      <guid>https://dev.to/miksus/new-horizon-in-automation-rocketry-2ni5</guid>
      <description>&lt;p&gt;There are plenty of scheduling options out there: cron, Airflow, APScheduler... However, they are all limited with the type of automation they are suitable for. Airflow was created for data engineers and cron for simple needs. There were no solutions for truly autonomous applications, until recently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rocketry
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Miksus/rocketry"&gt;Rocketry&lt;/a&gt; is a modern scheduling framework. It was designed to be easy to use, easy to customize and it has a unique take on scheduling. It does not force you to a specific structure and it can be seamlessly &lt;a href="https://github.com/Miksus/rocketry-with-fastapi"&gt;integrated with other frameworks such as FastAPI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A minimal example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rocketry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Rocketry&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rocketry.conds&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;daily&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Rocketry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;daily&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_daily&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;# This function runs once a day
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike the alternatives, Rocketry is a statement-based system: a task is run if its scheduling statement is true. This paradigm enables a lot of flexibility on scheduling and Rocketry natively supports cron-like scheduling, task pipelines and custom statements under the same generic mechanism. You can also arbitrarily combine the statements using basic logic: AND, OR and NOT. In contrast, Airflow has separate concepts for time scheduling, task pipelines and custom scheduling (sensors) and there are limitations on how you could combine them.&lt;/p&gt;

&lt;p&gt;A more advanced scheduling example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rocketry.conds&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after_success&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;# This is a custom condition. Should return True/False
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0 0 * * *"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_first&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"10 0 * * *"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;after_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;do_first&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;is_foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_second&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a lot more than just scheduling in the framework. It also has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parallelization/concurrency (async, threading, multiprocessing)&lt;/li&gt;
&lt;li&gt;Parameterization&lt;/li&gt;
&lt;li&gt;Task termination (custom or timeout)&lt;/li&gt;
&lt;li&gt;Keep task logs in memory, in a database or anywhere you like&lt;/li&gt;
&lt;li&gt;Modifiable runtime sessions (create/delete/modify tasks or restart the scheduler)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another example to demonstrate some more features:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rocketry.conds&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;daily&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_of_week&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;rocketry.args&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FuncArg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Return&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;daily&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"10:00"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;time_of_week&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FuncArg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="c1"&gt;# "arg"s value is the return of get_value
&lt;/span&gt;    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"World"&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;after_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;do_first&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"async"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_second&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;do_first&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="c1"&gt;# "arg"s value is the return of the task do_first
&lt;/span&gt;    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used decorated functions in the examples but Rocketry supports other task types as well: from shell commands (&lt;code&gt;app.task(command="echo 'Hello'")&lt;/code&gt;), from Python scripts (&lt;code&gt;app.task(path="path/to/script.py", func_name="main")&lt;/code&gt;) or just passing a function (&lt;code&gt;app.task(func=do_things)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In case you got interested, here are the relevant links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation: &lt;a href="https://rocketry.readthedocs.io/"&gt;https://rocketry.readthedocs.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source code: &lt;a href="https://github.com/Miksus/rocketry"&gt;https://github.com/Miksus/rocketry&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Releases: &lt;a href="https://pypi.org/project/rocketry/"&gt;https://pypi.org/project/rocketry/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might also like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Example) &lt;a href="https://github.com/Miksus/rocketry-with-fastapi"&gt;Rocketry + API + web UI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;(Article) &lt;a href="https://itnext.io/new-paradigm-on-scheduling-cf2e55950a0d"&gt;Rocketry's scheduling&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;(Article) &lt;a href="https://itnext.io/scheduler-with-an-api-rocketry-fastapi-a0f742278d5b"&gt;Scheduler with an API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;(Article) &lt;a href="https://medium.com/p/7d9d8e84b58b"&gt;Initial introduction to Rocketry&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rocketry's vision is to make creating autonomous applications as easy as possible. If you liked the project, help us by spreading the word and consider leaving it a star on Github. Rocketry is also open for contribution, regardless if they are big or small. It is free open-source framework and it is developed with a passion.&lt;/p&gt;

</description>
      <category>python</category>
      <category>tooling</category>
      <category>news</category>
    </item>
  </channel>
</rss>
