mirror of https://github.com/watcha-fr/synapse
Conflicts: synapse/storage/_base.pypull/4/merge
commit
10294b6082
@ -1,11 +1,11 @@ |
||||
Versioning is, like, hard for paginating backwards because of the number of Home Servers involved. |
||||
Versioning is, like, hard for backfilling backwards because of the number of Home Servers involved. |
||||
|
||||
The way we solve this is by doing versioning as an acyclic directed graph of PDUs. For pagination purposes, this is done on a per context basis. |
||||
The way we solve this is by doing versioning as an acyclic directed graph of PDUs. For backfilling purposes, this is done on a per context basis. |
||||
When we send a PDU we include all PDUs that have been received for that context that hasn't been subsequently listed in a later PDU. The trivial case is a simple list of PDUs, e.g. A <- B <- C. However, if two servers send out a PDU at the same to, both B and C would point at A - a later PDU would then list both B and C. |
||||
|
||||
Problems with opaque version strings: |
||||
- How do you do clustering without mandating that a cluster can only have one transaction in flight to a given remote home server at a time. |
||||
If you have multiple transactions sent at once, then you might drop one transaction, receive anotherwith a version that is later than the dropped transaction and which point ARGH WE LOST A TRANSACTION. |
||||
- How do you do pagination? A version string defines a point in a stream w.r.t. a single home server, not a point in the context. |
||||
If you have multiple transactions sent at once, then you might drop one transaction, receive another with a version that is later than the dropped transaction and which point ARGH WE LOST A TRANSACTION. |
||||
- How do you do backfilling? A version string defines a point in a stream w.r.t. a single home server, not a point in the context. |
||||
|
||||
We only need to store the ends of the directed graph, we DO NOT need to do the whole one table of nodes and one of edges. |
||||
|
@ -0,0 +1,112 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Copyright 2014 matrix.org |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
|
||||
from twisted.trial import unittest |
||||
from twisted.internet import defer |
||||
|
||||
from mock import Mock |
||||
import logging |
||||
|
||||
from synapse.server import HomeServer |
||||
from synapse.handlers.directory import DirectoryHandler |
||||
from synapse.storage.directory import RoomAliasMapping |
||||
|
||||
|
||||
logging.getLogger().addHandler(logging.NullHandler()) |
||||
|
||||
|
||||
class DirectoryHandlers(object): |
||||
def __init__(self, hs): |
||||
self.directory_handler = DirectoryHandler(hs) |
||||
|
||||
|
||||
class DirectoryTestCase(unittest.TestCase): |
||||
""" Tests the directory service. """ |
||||
|
||||
def setUp(self): |
||||
self.mock_federation = Mock(spec=[ |
||||
"make_query", |
||||
]) |
||||
|
||||
self.query_handlers = {} |
||||
def register_query_handler(query_type, handler): |
||||
self.query_handlers[query_type] = handler |
||||
self.mock_federation.register_query_handler = register_query_handler |
||||
|
||||
hs = HomeServer("test", |
||||
datastore=Mock(spec=[ |
||||
"get_association_from_room_alias", |
||||
]), |
||||
http_client=None, |
||||
http_server=Mock(), |
||||
replication_layer=self.mock_federation, |
||||
) |
||||
hs.handlers = DirectoryHandlers(hs) |
||||
|
||||
self.handler = hs.get_handlers().directory_handler |
||||
|
||||
self.datastore = hs.get_datastore() |
||||
|
||||
self.my_room = hs.parse_roomalias("#my-room:test") |
||||
self.remote_room = hs.parse_roomalias("#another:remote") |
||||
|
||||
@defer.inlineCallbacks |
||||
def test_get_local_association(self): |
||||
mocked_get = self.datastore.get_association_from_room_alias |
||||
mocked_get.return_value = defer.succeed( |
||||
RoomAliasMapping("!8765qwer:test", "#my-room:test", ["test"]) |
||||
) |
||||
|
||||
result = yield self.handler.get_association(self.my_room) |
||||
|
||||
self.assertEquals({ |
||||
"room_id": "!8765qwer:test", |
||||
"servers": ["test"], |
||||
}, result) |
||||
|
||||
@defer.inlineCallbacks |
||||
def test_get_remote_association(self): |
||||
self.mock_federation.make_query.return_value = defer.succeed( |
||||
{"room_id": "!8765qwer:test", "servers": ["test", "remote"]} |
||||
) |
||||
|
||||
result = yield self.handler.get_association(self.remote_room) |
||||
|
||||
self.assertEquals({ |
||||
"room_id": "!8765qwer:test", |
||||
"servers": ["test", "remote"], |
||||
}, result) |
||||
self.mock_federation.make_query.assert_called_with( |
||||
destination="remote", |
||||
query_type="directory", |
||||
args={"room_alias": "#another:remote"} |
||||
) |
||||
|
||||
@defer.inlineCallbacks |
||||
def test_incoming_fed_query(self): |
||||
mocked_get = self.datastore.get_association_from_room_alias |
||||
mocked_get.return_value = defer.succeed( |
||||
RoomAliasMapping("!8765asdf:test", "#your-room:test", ["test"]) |
||||
) |
||||
|
||||
response = yield self.query_handlers["directory"]( |
||||
{"room_alias": "#your-room:test"} |
||||
) |
||||
|
||||
self.assertEquals({ |
||||
"room_id": "!8765asdf:test", |
||||
"servers": ["test"], |
||||
}, response) |
Loading…
Reference in new issue