Gestione di più eventi asincroni: attendere l'elaborazione delle offerte in sospeso sulla nuova offerta?

0

Ho un problema di programmazione, che non so come risolvere. E mentre ho fornito un esempio del mio codice, sono interessato a una risposta concettuale su come risolvere questo problema.

In un evento tradeOffers , chiamo una funzione per ottenere un elenco di offerte ed elaborarle una per una utilizzando async.forEachOfSeries dal modulo Async.js. Tuttavia, se arriva una nuova offerta mentre le offerte in sospeso vengono ancora elaborate, la stessa offerta può essere elaborata più volte e anche restituire un errore non disponibile dell'offerta perché è già stato accettato. Questo è un problema perché la nuova offerta non viene valutata in modo efficace.

È possibile risolvere questo problema con una semplice callback o un flag vero / falso, oppure dovrei implementare una coda per le offerte? Se ho bisogno di usare una coda, vorrei evitare di usare SQL per memorizzare le offerte. O ho bisogno di un meccanismo di controllo più complesso per gestire nuovi eventi tradeOffers quando l'elaborazione è già in atto?

Attualmente sto usando steam-tradeoffers e steam-user modulo.

Per spiegare meglio la mia situazione attuale, ecco il codice:

    steam.on('tradeOffers', function(count) {
        if (count > 1 && bot_working == true) {
            processoffers();
        }
        });

    function processoffers() {
        if (bot_working) {
            offers.getOffers({
                get_received_offers: 1,
                active_only: 1,
                get_sent_offers: 0,
                get_descriptions: 1,
                time_historical_cutoff: Math.round(Date.now() / 1000),
                language: "en_us"
            }, function(error, body) {
                if(error) return;
                if(body.response.trade_offers_received){
                async.forEachOfSeries(body.response.trade_offers_received, function(offer, key, cboffer) {
                        if (offer.trade_offer_state == 2){
                            //process offer
                        }
                        }, function (err) {
                if (err) console.log(err.message);
                  console.log('Completed all incoming offers.');
                }
            ); //function foreach
        } //if trade tradeoffers
    }); //if getoffers
};
};
    
posta Skanker 10.01.2016 - 18:56
fonte

1 risposta

1

Se l'array che stai elaborando in modo asincrono può essere modificato da un altro codice, è probabile che a un certo punto avvengano problemi come questo. Il modo più semplice per evitare questo tipo di condizioni di gara è fare una copia difensiva .

Il bug di "accettazione multipla" che descrivi fa sembrare che questo callback stia mutando gli oggetti reali nella matrice, piuttosto che semplicemente cambiando quali oggetti contiene la matrice, quindi probabilmente dovrai utilizzare una copia profonda piuttosto che una copia superficiale per questo lavorare.

Idealmente, la copia difensiva verrà eseguita nell'implementazione di getOffers() prima di chiamare il callback, in modo che i siti di chiamata non debbano mai preoccuparsi di questi problemi. Personalmente, lancio sempre una copia difensiva ogni volta che implemento un metodo come questo, perché previene preventivamente tanti piccoli bug nel codice client. Sia che io usi una copia profonda o superficiale dipende da quanto controllo dovrei avere sugli oggetti che sto passando al codice cliente.

Ma a volte, la matrice o gli oggetti in essa contenuti potrebbero essere troppo grandi perché una copia difensiva profonda sia pratica. In tal caso, avrai bisogno di una soluzione più interessante. Non so se questo si applica al tuo problema, ma per completezza ...

  1. Potresti provare a garantire che tradeOffers non non venga eseguito mentre c'è una richiesta getOffers () non completata. Come hai suggerito, il modo più semplice per farlo è mantenere una coda di richieste ed elaborarle una alla volta. Ma anche questo approccio richiede il callback getOffers () per dirti in qualche modo quando è finito l'esecuzione di tutti i suoi bit asincroni. Affidarsi al codice cliente per restituire sempre una promessa o chiamare sempre un callback speciale quando è veramente fatto è ... rischioso per non dire altro.
  2. Una soluzione hacky veloce sarebbe quella di attenersi al codice completamente sincrono all'interno del callback getOffers (). Tuttavia, questo si basa sul presupposto che getOffers () chiama il callback in modo sincrono, piuttosto che in modo asincrono, altrimenti avete ancora un tick in cui un evento tradeOffers può entrare di nascosto. Forse vi capita di sapere che getOffers () chiama sempre le sue funzioni di callback in modo sincrono. Ma personalmente, anche se l'avessi saputo, questo tipo di sottile ipotesi temporale mi rende a disagio perché è un po 'troppo vicino a " rilasciando Zalgo ".
  3. È possibile memorizzare le offerte in un vero e proprio database, poiché la maggior parte dei database ha già risolto questo problema.

Nel caso non sia ovvio, andrei con un database quando i dati sono troppo grandi per essere copiati. Affidarsi ai database per effettuare operazioni di sollevamento pesante tende a prevenire un sacco di mal di testa.

    
risposta data 10.01.2016 - 20:51
fonte

Leggi altre domande sui tag