2015-11-11 17 views
6

Diciamo che ho un corpus di calcoli che voglio eseguire in modo asincrono utilizzando core.async, ma sfortunatamente alcune delle funzioni dipendono dall'output delle funzioni . Come faccio a strutturare questo in modo pulito nel mio codice, ottenendo anche le migliori prestazioni?In che modo si strutturano chiaramente le dipendenze tra i canali core.async?

alcune soluzioni potenziali che ho incontrato sono

  • Prismatic's Graph - sembra ragionevole, anche se non ho provato con canali core.async; il fatto che richieda l'uso di fnk è un po 'scoraggiante per me perché richiede l'acquisto nel loro DSL per le definizioni di funzione, ma se questa è la soluzione migliore allora non mi dispiace.
  • Javelin cells - solo per ClojureScript (attualmente) e utilizza FRP anziché CSP come implementazione, ma svolge un ottimo lavoro di modellazione delle dipendenze tra i calcoli tramite celle formula.
  • Onyx - creato per il calcolo distribuito (come concorrente di Apache Storm, ecc.) Ma ha un'astrazione di "flusso di lavoro" che gestisce le dipendenze tra i calcoli e funziona con core.async. Questo mi sembra il più adatto al mio dominio del problema, ma non sono sicuro di aver bisogno del sovraccarico di tutte le funzionalità di gestione dei cluster.

Qual è la soluzione canonica per questo problema?

Edit: aggiunto Onyx

+0

Sarebbe un [promessa] (https: // clojuredocs.org/clojure.core/promise) lavoro? –

+0

Qualche ragione particolare per cui non consideri la risposta alla tua domanda? –

risposta

1

Non credo ci sia un modo canonico per risolverlo, core.async è così nuovo che poche persone hanno dato un colpo. Se dovessi scegliere tra le tue tre opzioni, sceglierei Graph, è stato distribuito e testato in produzione per un po ', e non hai bisogno di Clojurescript per eseguirlo. Se sei interessato a una soluzione FRP, dai uno sguardo allo Java Reactive Extensions, i collegamenti Clojure per esso esistono nello RxClojure.

1

Questa domanda è un po 'difficile da rispondere perché la tua domanda manca di dettagli sul tuo caso d'uso. Le librerie come Graph, Javelin e Onyx hanno tutti casi d'uso diversi che vanno oltre il semplice fatto che i calcoli dipendono l'uno dall'altro.

Se si desidera che un thread o un blocco go dipenda dai risultati generati in un'altra parte del sistema, suggerirei di utilizzare solo le primitive core.async senza librerie aggiuntive.

La soluzione più semplice per rendere l'esecuzione in attesa di un altro thread di attività è l'utilizzo di blocchi di blocco quando si acquisiscono valori dai canali. Questo fermerà il thread (o go block) quando non ci sono valori disponibili su quel canale.

Come potete vedere nel seguente esempio, fare un calcolo dipende da un'attività svolta in un altro thread è molto semplice.

(let [c (chan)] 
    (thread (>!! c “hello”)) 
    (assert (= “hello” (<!! c))) 
    (close! c) 

Sono disponibili anche meccanismi più elaborati. La funzione Alts!! offre la possibilità di attendere su più canali contemporaneamente. Diverse varianti della funzione pipeline consentono di modellare la concorrenza in un modo simile al flusso di dati.

Ci sono problemi specifici in cui ci si imbatte e che non possono essere espressi chiaramente utilizzando le funzioni built-in?

+0

Forse questo invece? (let [c (chan)] (vai (> !! c "ciao")) (assert (= "ciao" ( ctpenrose