2012-07-12 22 views
5

Ana Django uygulama işlemimde bir Kereviz görevinin sonucuna nasıl erişebilirim? Ya da, mevcut bir soket bağlantısına ayrı bir işlemden nasıl yayımlayabilirim?Celery ile django-socketio: eşzamansız görev tamamlandıktan sonra sokete gönder

Kullanıcıların puan aldığı bir uygulamam var. Bir skor kaydedildiğinde, hesaplamalar yapılır (hedeflere doğru ilerlemek, vb.) Ve bu hesaplamalara dayanarak ilgili kullanıcılara bildirimler gönderilir. Hesaplamalar 30s + sürdürebilir, bu nedenle zayıf kullanıcı arayüzünden kaçınmak için, bu işlemler Puan modelimin post_save sinyali tarafından çağrılan bir Kereviz görevi aracılığıyla bir arka plan işleminde gerçekleştirilir.

İdeal olarak benim Nofication modelimin post_save sinyali, abone olan istemcilere bir mesaj yayınlayacaktır (django-socketio, gevent-socketio için bir sarıcı kullanıyorum). Bu

  1. Bildirimine Dair kaydetmek kapmak bir Bildirim, bir arka plan işlemi bu hesaplamalara dayanarak
  2. yeni Skor örneğinde Hesaplama yapmak bir Skoru
  3. oluşturun ... basit görünüyor örneği ve bu mümkün emin değilim şu denedikten sonra

Ancak soket bağlantısı üzerinden abone müşterilerine yayımlamak:

  • görev tarafından çağrılan geri arama yöntemi gevent en SocketIOServer örneği geçen, fakat bu

  • memchache ve (Django'nın session_id farklı) soket session_id depolanması mümkün değildir geçirilen nesne, dekapaj gerektirir Kereviz görev sürecinde bunu almak.

  • Redis pubsub kullanarak, bir arka plan işleminde oluşturulan modellerde post_save sinyalleri tarafından çağrılan yöntemler bir Redis kanalına basitçe yayınlayabilir, ancak ana uygulama işleminde (soket bağlantısına erişimi olan) sohbet kanalını dinlemeyi engeller. uygulamanın geri kalanı.

  • Ayrıca, her bir yuva abonesi için oluşturulan her Redis istemcisi için yeni iş parçacıkları oluşturmayı denedim. Bildiğim kadarıyla söyleyebilirim bu yeni gevent.greenlets.Greenlet yumurtlama gerektirir ve gevent birden çok iş parçacığı

içinde kullanılamaz Şüphesiz bu bir çözülmüş bir sorundur. Neyi kaçırıyorum?

+1

Bazı kodları gösterebilir misiniz?Gereksinimleri anladım, ama teşebbüs ettiğin uygulama net değil. Tasks.py ve views.py'iniz neye benziyor (bu dosya yapısını kullandığınızı varsayarsak)? –

+0

Yuva işleyicileriniz sunucuda başlatıldığında ne yapar? redis pub alt sırasına mı abone olurlar? Eğer öyleyse, redis-py gevent monkeypatch kullanıyor musunuz? aplannızda bir yerde bu satırı koymak zorundasınız: 'import redis, gevent; redis.connection.socket = gevent.socket' https://github.com/andymccurdy/redis-py/pull/199. Anlaşılması gereken şey, yivli yamaların/dosya tanıtıcılarının kullanılmasına özen göstermemeniz durumunda, lokma işleyicileri gibi açık yeşil renklerin hala işlemi engelleyeceğidir. – Thomas

cevap

0

Zaten yazık :) olacağını REDIS bir pub/sub yazma, django-socketio sahip

istemci tarafı:

var socket = new io.Socket(); 
socket.connect(); 
socket.on('connect', function() { 
    socket.subscribe({{ score_update_channel }}); 
}); 

sunucu tarafı: İhtiyacınız

from django_socketio import broadcast_channel 
def user_score_update(user): 
    return 'score_updates_user_%s' % user.pk 

channel = user_score_update(user) 
broadcast_channel(score_result_data, channel) 

django-socketio prosesinde yayını çalıştırmak için; Eğer bunu farklı bir süreçten (kereviz işçisi) çalıştırırsanız işe yaramaz (kanallar django-socketio süreci tarafından belleğe referans olarak verilir); Bunu bir görünümde sararak ve görev tamamlandığında, kerevizin çağırarak (gerçek bir http isteği yaparak) çözebilirsiniz.

İlgili konular