mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-20 10:55:09 +03:00
Merge remote-tracking branch 'origin/dinsic' into dbkr/user_directory_defer_to_is
This commit is contained in:
commit
8fddcf703e
6 changed files with 26 additions and 14 deletions
|
@ -114,6 +114,8 @@ class RegistrationConfig(Config):
|
||||||
|
|
||||||
# If enabled, user IDs, display names and avatar URLs will be replicated
|
# If enabled, user IDs, display names and avatar URLs will be replicated
|
||||||
# to this server whenever they change.
|
# to this server whenever they change.
|
||||||
|
# This is an experimental API currently implemented by sydent to support
|
||||||
|
# cross-homeserver user directories.
|
||||||
# replicate_user_profiles_to: example.com
|
# replicate_user_profiles_to: example.com
|
||||||
|
|
||||||
# Users who register on this homeserver will automatically be joined
|
# Users who register on this homeserver will automatically be joined
|
||||||
|
|
|
@ -53,6 +53,9 @@ class ProfileHandler(BaseHandler):
|
||||||
if len(self.hs.config.replicate_user_profiles_to) > 0:
|
if len(self.hs.config.replicate_user_profiles_to) > 0:
|
||||||
reactor.callWhenRunning(self._assign_profile_replication_batches)
|
reactor.callWhenRunning(self._assign_profile_replication_batches)
|
||||||
reactor.callWhenRunning(self._replicate_profiles)
|
reactor.callWhenRunning(self._replicate_profiles)
|
||||||
|
# Add a looping call to replicate_profiles: this handles retries
|
||||||
|
# if the replication is unsuccessful when the user updated their
|
||||||
|
# profile.
|
||||||
self.clock.looping_call(
|
self.clock.looping_call(
|
||||||
self._replicate_profiles, self.PROFILE_REPLICATE_INTERVAL
|
self._replicate_profiles, self.PROFILE_REPLICATE_INTERVAL
|
||||||
)
|
)
|
||||||
|
@ -109,7 +112,7 @@ class ProfileHandler(BaseHandler):
|
||||||
signed_body = sign_json(body, self.hs.hostname, self.hs.config.signing_key[0])
|
signed_body = sign_json(body, self.hs.hostname, self.hs.config.signing_key[0])
|
||||||
try:
|
try:
|
||||||
yield self.http_client.post_json_get_json(url, signed_body)
|
yield self.http_client.post_json_get_json(url, signed_body)
|
||||||
self.store.update_replication_batch_for_host(host, batchnum)
|
yield self.store.update_replication_batch_for_host(host, batchnum)
|
||||||
logger.info("Sucessfully replicated profile batch %d to %s", batchnum, host)
|
logger.info("Sucessfully replicated profile batch %d to %s", batchnum, host)
|
||||||
except Exception:
|
except Exception:
|
||||||
# This will get retried when the looping call next comes around
|
# This will get retried when the looping call next comes around
|
||||||
|
|
|
@ -65,16 +65,14 @@ class ProfileWorkerStore(SQLBaseStore):
|
||||||
desc="get_profile_avatar_url",
|
desc="get_profile_avatar_url",
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def get_latest_profile_replication_batch_number(self):
|
def get_latest_profile_replication_batch_number(self):
|
||||||
def f(txn):
|
def f(txn):
|
||||||
txn.execute("SELECT MAX(batch) as maxbatch FROM profiles")
|
txn.execute("SELECT MAX(batch) as maxbatch FROM profiles")
|
||||||
rows = self.cursor_to_dict(txn)
|
rows = self.cursor_to_dict(txn)
|
||||||
return rows[0]['maxbatch']
|
return rows[0]['maxbatch']
|
||||||
max_batch = yield self.runInteraction(
|
return self.runInteraction(
|
||||||
"get_latest_profile_replication_batch_number", f,
|
"get_latest_profile_replication_batch_number", f,
|
||||||
)
|
)
|
||||||
defer.returnValue(max_batch)
|
|
||||||
|
|
||||||
def get_profile_batch(self, batchnum):
|
def get_profile_batch(self, batchnum):
|
||||||
return self._simple_select_list(
|
return self._simple_select_list(
|
||||||
|
@ -86,7 +84,6 @@ class ProfileWorkerStore(SQLBaseStore):
|
||||||
desc="get_profile_batch",
|
desc="get_profile_batch",
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def assign_profile_batch(self):
|
def assign_profile_batch(self):
|
||||||
def f(txn):
|
def f(txn):
|
||||||
sql = (
|
sql = (
|
||||||
|
@ -98,17 +95,14 @@ class ProfileWorkerStore(SQLBaseStore):
|
||||||
)
|
)
|
||||||
txn.execute(sql, (BATCH_SIZE,))
|
txn.execute(sql, (BATCH_SIZE,))
|
||||||
return txn.rowcount
|
return txn.rowcount
|
||||||
assigned = yield self.runInteraction("assign_profile_batch", f)
|
return self.runInteraction("assign_profile_batch", f)
|
||||||
defer.returnValue(assigned)
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def get_replication_hosts(self):
|
def get_replication_hosts(self):
|
||||||
def f(txn):
|
def f(txn):
|
||||||
txn.execute("SELECT host, last_synced_batch FROM profile_replication_status")
|
txn.execute("SELECT host, last_synced_batch FROM profile_replication_status")
|
||||||
rows = self.cursor_to_dict(txn)
|
rows = self.cursor_to_dict(txn)
|
||||||
return {r['host']: r['last_synced_batch'] for r in rows}
|
return {r['host']: r['last_synced_batch'] for r in rows}
|
||||||
result = yield self.runInteraction("get_replication_hosts", f)
|
return self.runInteraction("get_replication_hosts", f)
|
||||||
defer.returnValue(result)
|
|
||||||
|
|
||||||
def update_replication_batch_for_host(self, host, last_synced_batch):
|
def update_replication_batch_for_host(self, host, last_synced_batch):
|
||||||
return self._simple_upsert(
|
return self._simple_upsert(
|
||||||
|
|
|
@ -13,10 +13,23 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a batch number to track changes to profiles and the
|
||||||
|
* order they're made in so we can replicate user profiles
|
||||||
|
* to other hosts as they change
|
||||||
|
*/
|
||||||
ALTER TABLE profiles ADD COLUMN batch BIGINT DEFAULT NULL;
|
ALTER TABLE profiles ADD COLUMN batch BIGINT DEFAULT NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Index on the batch number so we can get profiles
|
||||||
|
* by their batch
|
||||||
|
*/
|
||||||
CREATE INDEX profiles_batch_idx ON profiles(batch);
|
CREATE INDEX profiles_batch_idx ON profiles(batch);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A table to track what batch of user profiles has been
|
||||||
|
* synced to what profile replication target.
|
||||||
|
*/
|
||||||
CREATE TABLE profile_replication_status (
|
CREATE TABLE profile_replication_status (
|
||||||
host TEXT NOT NULL,
|
host TEXT NOT NULL,
|
||||||
last_synced_batch BIGINT NOT NULL
|
last_synced_batch BIGINT NOT NULL
|
||||||
|
|
|
@ -75,7 +75,7 @@ class ProfileTestCase(unittest.TestCase):
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def test_get_my_name(self):
|
def test_get_my_name(self):
|
||||||
yield self.store.set_profile_displayname(
|
yield self.store.set_profile_displayname(
|
||||||
self.frank.localpart, "Frank", 1
|
self.frank.localpart, "Frank", 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
displayname = yield self.handler.get_displayname(self.frank)
|
displayname = yield self.handler.get_displayname(self.frank)
|
||||||
|
@ -135,7 +135,7 @@ class ProfileTestCase(unittest.TestCase):
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def test_get_my_avatar(self):
|
def test_get_my_avatar(self):
|
||||||
yield self.store.set_profile_avatar_url(
|
yield self.store.set_profile_avatar_url(
|
||||||
self.frank.localpart, "http://my.server/me.png", 1
|
self.frank.localpart, "http://my.server/me.png", 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
avatar_url = yield self.handler.get_avatar_url(self.frank)
|
avatar_url = yield self.handler.get_avatar_url(self.frank)
|
||||||
|
|
|
@ -40,7 +40,7 @@ class ProfileStoreTestCase(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
yield self.store.set_profile_displayname(
|
yield self.store.set_profile_displayname(
|
||||||
self.u_frank.localpart, "Frank", 1
|
self.u_frank.localpart, "Frank", 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
|
@ -55,7 +55,7 @@ class ProfileStoreTestCase(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
yield self.store.set_profile_avatar_url(
|
yield self.store.set_profile_avatar_url(
|
||||||
self.u_frank.localpart, "http://my.site/here", 1
|
self.u_frank.localpart, "http://my.site/here", 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
|
|
Loading…
Reference in a new issue