当新消息到达时,终止先前的autobahn websocket调用



我正在设计一个功能,通过websocket提供类似自动完成的搜索结果。当用户输入足够快时,他们之前的查询往往会过时,因为他们已经在查询新的信息了。

是否有任何方法可以识别新的查询,并终止以前的查询?我尝试检查当新消息传入时查询是否正在处理,但似乎新消息仅在之前的查询(我想取消的查询)完成后处理。我也很困惑,当有多个用户同时搜索时,这将如何工作。

from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
import json
from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
running = 'no'
def main_search(query): # May take up to 400ms to process
    ...

class SearchServerProtocol(WebSocketServerProtocol):
    @inlineCallbacks
    def onMessage(self, payload, isBinary):
        if not isBinary:
            x = json.loads(payload.decode('utf8'))
            global running
            try:
                print running
                running = 'yes'
                res = yield main_search(x['query'])
                running = 'no'
                print x['query']
            except Exception as e:
                print e
                self.sendClose(1000)
            else:
                self.sendMessage(json.dumps(res).encode('utf8'))

if __name__ == '__main__':
    import sys
    from twisted.python import log
    from twisted.internet import reactor
    log.startLogging(sys.stdout)
    factory = WebSocketServerFactory("ws://104.236.31.77:8080", debug=False)
    factory.protocol = SearchServerProtocol
    reactor.listenTCP(8080, factory)
    reactor.run()

print running总是返回no。

谢谢!

我认为您需要某种表示您的用户会话(或搜索会话)的上下文对象。在这种情况下,你可以放一个latestSearchId,每次搜索都增加。然后在main_search中添加searchId参数。假设您有一个循环或其他可以中止的阶段,您可以通过将当前搜索中的searchId与搜索会话的latestSearchId进行比较来测试当前搜索中的searchId是否仍然是最新的。

另一种方法(例如,如果您不能中止搜索)可以在计算搜索之前等待几毫秒,并同时检查是否有新的搜索进入。

根据您的评论编辑

你的问题是你永远不应该阻塞反应堆回路。你需要做的是把你的main_search切成碎片,这样你就可以把控制交还给反应堆回路。

您是否可以这样做:

def resume_search(position):
    #stuff
reactor.callLater(0, resume_search, current_position)

反应堆。callLater将安排函数在完成其工作后立即被调用。你应该把反应堆环路看作一个大的while True它基本上做三件事

  • 检查传入IO
  • 执行你的东西(它正在处理事件)
  • 发送输出IO

只要你的代码一直在运行,它就永远不会到达另外两个。所以当你插入一个反应堆。callLater,它将运行反应器循环,直到延迟变量(在我们的示例中可以为0)通过。注意,不能保证它会及时调用您的函数。这是因为很有可能某些东西运行(阻塞反应堆)的时间超过了您指定的时间间隔。所以你应该看到这个reactor.callLater(0, fun)是"call me when you're not busy"

最新更新