2011-01-13 20 views
1

Ich arbeite an einer Multi-User-App zum Bearbeiten von Bäumen. Es verwendet resque gem für Hintergrundprozesse. Um Runtime-Multiuser-Konflikte zu vermeiden, möchte ich Befehlsmuster verwenden und Benutzeraktionen in einer resque-Warteschlange speichern. Wenn also jemand einen Zweig löscht, kann ein anderer Benutzer Kinder dieses Zweigs nicht bearbeiten.Verwenden von resque zum Implementieren eines Befehlsmusters

Es funktioniert, aber es ist ziemlich langsam, den Job zum ersten Mal aus einer Warteschlange auszuwählen, weil Resque Worker die Jobs im 5-Sekunden-Intervall überprüft. Es verlangsamt die Bearbeitungsoberfläche erheblich. Es ist possibe, so etwas zu tun:

cmd = MyCommand.create!(:attr1 => 'foo', :attr2 => 'bar') 
    Resque.enqueue(MyCommand, cmd.id) 
    workers = Resque.workers.select {|w| w.queues.include?('my_queue') } 
    raise "Should be only one queue for commands!" if workers.size != 1 
    not_done = true 
    while not_done 
     not_done = workers[0].process 
    end 

Es tut, was ich brauche, aber ich frage mich, ob es eine elegantere Art und Weise, dies zu tun ist. Außerdem ist: process eine veraltete Methode für Worker-Instanzen.

Antwort

2

Ich denke, Ihr Design Ansatz ist etwas solide, aber Redis/Resque möglicherweise nicht angemessen. Was Sie wollen, ist eine super schnelle In-Memory-Queue, die Resque ähnlich ist, aber das hat keine Polling-Verzögerung.

Ich bin mir ziemlich sicher, dass Sie MemCached dafür verwenden können, aber es gibt vielleicht andere Optionen. Jede Lösung, bei der die in die Warteschlange eingereihten Befehle in bestimmten Intervallen abgerufen werden müssen, würde wahrscheinlich keine akzeptable Leistung für die kollaborative Bearbeitung bieten, es sei denn, es ist in Ordnung, alle 100 ms oder noch öfter abzufragen.

Wenn Sie schließlich jede Aktion in eine einzige Warteschlange stellen, die nur seriell Befehle verarbeiten kann (nacheinander), werden Sie zwangsläufig in eine Situation geraten, in der die Warteschlange gesichert wird, weil zu viele Befehle kommen in, und sie verarbeiten nicht so schnell. Aus diesem Grund ist eine skalierbarere Lösung möglicherweise die Verwendung der Versionierung, bei der jedes Element der Struktur versioniert wird, und bei Aktualisierung/Änderung werden alle untergeordneten Elemente ebenfalls mit einer neuen Version aktualisiert. Auf diese Weise wird eine Bearbeitung einer älteren Versionsnummer abgelehnt.

Wie auch immer .. viel Glück, klingt wie ein nicht-triviales Problem zu lösen.

+0

Ich bin beeindruckt von resque/redis Geschwindigkeit und es macht mir nichts aus, wenn es eine Latenz weniger als 10-20 Millisekunden für GUI gibt. Resque ermöglicht auch die Verwendung eines separaten Prozessors für bestimmte Aufgaben out-of-the-box. Jetzt sehe ich keinen starken Grund, zu einer Memcached- oder Inmemory-Lösung zu wechseln – dimus

Verwandte Themen