Come posso programmare l'esecuzione del codice ogni poche ore nel framework Elixir o Phoenix?


194

Quindi diciamo che voglio inviare un sacco di e-mail o ricreare una sitemap o qualsiasi altra ogni 4 ore, come potrei farlo a Phoenix o semplicemente con Elisir?

Risposte:


390

Esiste una semplice alternativa che non richiede dipendenze esterne:

defmodule MyApp.Periodically do
  use GenServer

  def start_link do
    GenServer.start_link(__MODULE__, %{})
  end

  def init(state) do
    schedule_work() # Schedule work to be performed at some point
    {:ok, state}
  end

  def handle_info(:work, state) do
    # Do the work you desire here
    schedule_work() # Reschedule once more
    {:noreply, state}
  end

  defp schedule_work() do
    Process.send_after(self(), :work, 2 * 60 * 60 * 1000) # In 2 hours
  end
end

Ora nel tuo albero di supervisione:

worker(MyApp.Periodically, [])

170
È impossibile non amare questa lingua :)
NoDisplayName

3
Dove devo mettere questo file? Sotto lib / directory del progetto Phoenix? Dove va il test, testare / periodicamente / *?
EugZol,

9
In lib perché è un processo di lunga durata. Puoi mettere il test in qualsiasi modo abbia senso, magari "test / my_app / periodically_test.exs".
José Valim,

2
Qualche motivo particolare per non spostarsi Process.send_afternella propria funzione in modo che la funzione possa essere chiamata da entrambi inite handle_info?
Ryan Bigg,

24
@CodyPoll :timer.send_intervalva bene, ma tieni presente che gli intervalli saranno costanti. Quindi immagina di voler fare qualcosa ogni minuto e, in futuro, il lavoro stesso richiede più di un minuto. In questi casi, lavoreresti continuamente e la coda dei messaggi aumenterebbe senza limiti. La soluzione sopra attenderà sempre il periodo indicato dopo il completamento del lavoro.
José Valim,

33

quantistico consente di creare, trovare ed eliminare lavori in fase di esecuzione.

Inoltre, puoi passare argomenti alla funzione task durante la creazione di un cronjob e persino modificare il fuso orario se non sei soddisfatto di UTC.

Se la tua app viene eseguita come istanze multiple isolate (ad es. Heroku), ci sono processori supportati da PostgreSQL o Redis, che supportano anche la pianificazione delle attività:

Oban: https://github.com/sorentwo/oban

Exq: https://github.com/akira/exq

Toniq: https://github.com/joakimk/toniq

Verk: https://github.com/edgurgel/verk


1
Penso che sarà eccessivo per molte attività semplici che non lo richiedono, ma grazie comunque per la risposta.
NoDisplayName

Avere un elenco di biblioteche disponibili è stato utile per me.
Sheldonkreger,

25

Puoi usare erlcron per questo. Lo usi come

job = {{:weekly, :thu, {2, :am}},
  {:io, :fwrite, ["It's 2 Thursday morning~n"]}}

:erlcron.cron(job)

A jobè una tupla a 2 elementi. Il primo elemento è una tupla che rappresenta la pianificazione per il lavoro e il secondo elemento è la funzione o un MFA (Modulo, Funzione, Arità). Nell'esempio sopra, eseguiamo :io.fwrite("It's 2 Thursday morning")ogni 2:00 di giovedì.

Spero che aiuti!


Sì, è meglio di niente, grazie. Lascerò la domanda senza risposta per un po ', forse ci saranno altri suggerimenti
NoDisplayName

4
Prego! C'è anche github.com/c-rack/quantum-elixir che è una lib di elisir, se preferisci
Gjaldon,

6

Ho usato la libreria Quantum Quantum -Elixir .
Seguire le istruzioni seguenti.

#your_app/mix.exs
defp deps do
  [{:quantum, ">= 1.9.1"},  
  #rest code
end



#your_app/mix.exs
def application do
  [mod: {AppName, []},
   applications: [:quantum,
   #rest code         
 ]]
end

#your_app/config/dev.exs
config :quantum, :your_app, cron: [
  # Every minute
  "* * * * *": fn -> IO.puts("Hello QUANTUM!") end
]

Tutto stabilito. Avviare il server eseguendo il comando seguente.

iex -S mix phoenix.server 

Questo è come cronjobs
DarckBlezzer

1

Trovo :timer.send_interval/2un po 'più ergonomico da usare con un GenServerrispetto Process.send_after/4(usato nella risposta accettata ).

Invece di dover riprogrammare la tua notifica ogni volta che la gestisci, :timer.send_interval/2imposta un intervallo in cui ricevi un messaggio all'infinito, non è necessario continuare a chiamare schedule_work()come usa la risposta accettata.

defmodule CountingServer do
  use GenServer

  def init(_) do
    :timer.send_interval(1000, :update)
    {:ok, 1}
  end

  def handle_info(:update, count) do
    IO.puts(count)
    {:noreply, count + 1}
  end
end

Ogni 1000 ms (ovvero, una volta al secondo), IntervalServer.handle_info/2verrà chiamato, stampa la corrente counte aggiorna lo stato del GenServer ( count + 1), dandoti un output come:

1
2
3
4
[etc.]


0

Quantum è fantastico, lo usiamo sul posto di lavoro come sostituto del cron con un front-end di Phoenix e aggiungiamo anche lavori in tempo reale che è molto pulito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.