<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="279792" data-post-id="279792">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>If you want the shortest possible out-of-the-box solution with no external dependency, there’s <a href="https://www.erlang.org/doc/man/timer.html#apply_interval-4" rel="nofollow">:timer.apply_interval</a>.</p>
<p>Such solution should be no worse than a custom <code>GenServer</code> +<code>send_after</code>.</p>
<p>My preferred approach though is a <code>GenServer</code> which starts the task as a child process. It also has to be one <code>GenServer</code> per each periodic job, so I can inject each job in the proper place in a supervision tree. This is a big reason why I don’t like and avoid quantum &amp; similar libs.</p>
<p>Instead I wrote my own periodic abstraction which follows the principles outlined above. I blogged a bit about it <a href="https://www.theerlangelist.com/article/periodic" rel="noopener nofollow ugc">here</a>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="279792" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/doing-something-every-few-hours-the-simplest-approach/54177/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-279792" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="279792"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="279798" data-post-id="279798">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="BartOtten" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/BartOtten/120/25440_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  BartOtten
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="sasajuric" data-post="12" data-topic="54177">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>My preferred approach though is a <code>GenServer</code> which starts the task as a child process. It also has to be one <code>GenServer</code> per each periodic job, so I can inject each job in the proper place in a supervision tree. This is a big reason why I don’t like and avoid quantum &amp; similar libs.</p>
</blockquote>
</aside>
<p>I also took this approach. As a result I can pause, speedup and slowdown the interval by making calls to a jobs GenServer. When the Genserver goes down (by calling ‘halt’ or due to an error) the state is saved and used in recovery.</p>
<p>An improvement I envision is using a state machine. Can’t recall why but it had to do something with the interval and allowed transisions <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="279798" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/doing-something-every-few-hours-the-simplest-approach/54177/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-279798" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="279798"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="279958" data-post-id="279958">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimitarvp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/120/38664_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimitarvp
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Seconding <a class="mention" href="/u/sasajuric" rel="nofollow">@sasajuric</a> and <a class="mention" href="/u/bartotten" rel="nofollow">@BartOtten</a> here, just roll your own <code>GenServer</code> per task – it’s just 10-20 coding lines of boilerplate maximum.</p>
<p>Or use <a href="https://hexdocs.pm/periodic/Periodic.html" rel="noopener nofollow ugc"><code>Periodic</code></a>. It’s a very small and functional thing (last I used it at least, which was like 3 years ago). Or you can rip out the code you need from it because again, it’s very small and works fine.</p>
<p>I would make a few <code>GenServer</code>s though. It’s a one-time investment that can pay huge dividends. If you want to get slightly fancy maybe you can store “when was the last time task X ran” in a small file; though you mentioned that it’s not critical if a task gets executed a bit more rarely every now and then (when the app is rebooted) so if that’s indeed the case then it’s probably best to not bother with keeping state outside of memory.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="279958" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/doing-something-every-few-hours-the-simplest-approach/54177/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-279958" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="279958"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="279976" data-post-id="279976">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Sebb" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Sebb/120/21818_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Sebb
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>didnt use any of these, but the cron-syntax maybe nice to have.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="279976" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/doing-something-every-few-hours-the-simplest-approach/54177/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-279976" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="279976"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="280085" data-post-id="280085">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="wallyfoo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/wallyfoo/120/16837_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  wallyfoo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Jumping on here. What do we mean by “simple”? <img src="https://forum.elixirforum.com/images/emoji/apple/grinning.png?v=15" title=":grinning:" class="emoji" alt=":grinning:" loading="lazy" width="20" height="20"></p>
<p>I’m using Quantum (shared by <a class="mention" href="/u/sebb" rel="nofollow">@Sebb</a> above) for a process that I need to fire off every 24 hours. I don’t care if it has a response or not, and I gave the process a ripcord to alert me if it fails catastrophically. I initially began building a genserver for my task before I realized I was over-engineering for this particular case.  Implementing Quantum took me slightly longer than it takes to type <code>mix deps.get</code> and hit return. Simple.</p>
<p>If I needed to maintain state or recover a user session in a meaningful way, I would definitely go with a “simple” GenServer implementation. But this entails more code to maintain and test. On the other hand, a GenServer may be more flexible in the long run if my organization adds more requirements to the task.</p>
<p>For me, the most important consideration for this kind of “how long is a piece of string” question is always: what’s the right tool for the job?</p>
<p>How much time do you have to implement it? Is the job this task performs actually <em>important</em>? Can you commit to maintaining it? Do I need crash protection? Will the application fail if this piece isn’t running reliably? Or is this job a nice-to-have bit that’s not going to inconvenience anyone if it doesn’t run every day?</p>
<p>Simple in one regard probably means tradeoffs in another, right?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280085" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/doing-something-every-few-hours-the-simplest-approach/54177/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-280085" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280085"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="280510" data-post-id="280510">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jarmo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jarmo/120/26312_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jarmo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Wouldn’t the simplest case be to create a mix/release task and just execute it via Linux/Unix crontab? If your task outputs something to the console in case of errors and mail server at localhost is setup then you will also start to receive e-mails in case of unexpected errors. This all works pretty much out of the box. In addition - it’s also really easy to start these tasks manually from command line if there’s a need.</p>
<p>Of course this kind of approach is only usable if you are running Linux/Unix, you have access to the server and it doesn’t matter if previous task has not finished before launching a new task. Otherwise a locking mechanism needs to be implemented, but this is also pretty trivial by just creating some “lock” file when starting the task and deleting it in the end.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280510" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/doing-something-every-few-hours-the-simplest-approach/54177/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-280510" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280510"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>