Используя twisted.web классы Twisted, как я сбрасываю свои исходящие буферы?

Когда я изучил это некоторое время назад, я пришел к выводу, что нет единого правильного ответа.

Я закончил проверкой только свойства @Id в equals() и hashCode(), так как это, казалось, работало лучше всего. (Мы не используем @NaturalId s; вместо этого он мог бы работать с этим, но может быть безопаснее придерживаться @Id.)

Я думаю, что единственная потенциальная проблема, с которой я столкнулся, была если новый экземпляр добавляется в коллекцию перед сохранением. На практике этого никогда не происходит в нашем проекте, и поэтому он работает хорошо. (Если это произойдет в вашем проекте, вы все равно можете найти это лучшим компромиссом, чтобы избежать проблем, когда сохраняются объекты появляются в коллекциях, что встречается гораздо чаще.)

Как и другие ответы указали, что если вы переопределяете equals(), вы должны также переопределять hashCode(), чтобы гарантировать, что равные объекты всегда имеют одинаковый хэш-код. (Первый пример вопроса соответствует этому, хотя, возможно, это немного сбивает с толку, когда два метода не проверяют все одинаковые поля.)

Кстати, в Котлине эти два метода становятся незначительно управляемыми: [ 1115]

override fun equals(other: Any?) = other === this
                                || (other is MyEntity && entityId == other.entityId)

override fun hashCode() = entityId

(Еще один пример того, почему я люблю Котлина!)

9
задан Hans Sjunnesson 22 April 2009 в 10:57
поделиться

2 ответа

Using time.sleep() prevents twisted from doing its job. To make it work you can't use time.sleep(), you must return control to twisted instead. The easiest way to modify your existing code to do that is by using twisted.internet.defer.inlineCallbacks, which is the next best thing since sliced bread:

#!/usr/bin/env python

import time

from twisted.web import http
from twisted.internet import protocol
from twisted.internet import reactor
from twisted.internet import defer

def wait(seconds, result=None):
    """Returns a deferred that will be fired later"""
    d = defer.Deferred()
    reactor.callLater(seconds, d.callback, result)
    return d

class StreamHandler(http.Request):
    BOUNDARY = 'BOUNDARY'

    def writeBoundary(self):
        self.write("--%s\n" % (self.BOUNDARY))

    def writeStop(self):
        self.write("--%s--\n" % (self.BOUNDARY))

    @defer.inlineCallbacks
    def process(self):
        self.setHeader('Connection', 'Keep-Alive')
        self.setHeader('Content-Type', "multipart/x-mixed-replace;boundary=%s" % (self.BOUNDARY))

        self.writeBoundary()

        self.write("Content-Type: text/html\n")
        s = "<html>foo</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)
        self.writeBoundary()


        yield wait(2)

        self.write("Content-Type: text/html\n")
        s = "<html>bar</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)
        self.writeBoundary()

        yield wait(2)

        self.write("Content-Type: text/html\n")
        s = "<html>baz</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)

        self.writeStop()

        self.finish()


class StreamProtocol(http.HTTPChannel):
    requestFactory = StreamHandler

class StreamFactory(http.HTTPFactory):
    protocol = StreamProtocol


if __name__ == '__main__':   
    reactor.listenTCP(8800, StreamFactory())
    reactor.run()

That works in firefox, I guess it answers your question correctly.

10
ответ дан 4 December 2019 в 20:24
поделиться

Причина, по-видимому, объяснена в FAQ для витая . Витой сервер на самом деле ничего не записывает в подчеркивающее соединение, пока поток реактора не будет запущен, в данном случае в конце вашего метода. Однако вы можете использовать реактор.doSelect (тайм-аут) перед каждым вашим сном, чтобы заставить реактор написать, что он имеет для соединения.

в этом случае в конце вашего метода. Однако вы можете использовать реактор.doSelect (тайм-аут) перед каждым вашим сном, чтобы заставить реактор написать, что он имеет для соединения.

в этом случае в конце вашего метода. Однако вы можете использовать реактор.doSelect (тайм-аут) перед каждым вашим сном, чтобы заставить реактор написать, что он имеет для соединения.

1
ответ дан 4 December 2019 в 20:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: