Skip to content

Commit c47cfb7

Browse files
committed
Cache room active_users
This replaces active counts of room_users to get the active user count, instead caching the current value in a new `rooms.active_users` column, updating it every 10s during the cleanup task. The count ended up being moderately expensive, (the most expensive regular query we have right now since the earlier change on this branch), and gets worse both as the count gets larger and as the table gets increasingly fragmented. It isn't a noticeable problem *yet* because legacy Session clients only query room info once in a while (seemingly randomly) but new Session endpoints will hit this much more often and so this preemptively addresses the issue.
1 parent e24cb00 commit c47cfb7

File tree

14 files changed

+102
-38
lines changed

14 files changed

+102
-38
lines changed

contrib/upgrade-tests/common.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,7 @@ do_upgrades() {
101101
# This should exit cleanly to indicate no needed migrations (if it doesn't, i.e. we still
102102
# require migrations after doing a migration then Something Getting Wrong in migrations).
103103
python3 -msogs --check-upgrades
104+
105+
# Run the cleanup job to make sure we have the proper rooms.active_users values
106+
python3 -c 'from sogs.cleanup import cleanup; cleanup()'
104107
}

contrib/upgrade-tests/v0.1.10-expected.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
rooms:
2-
+----+------------+-------------------+-------------+-------+--------------+------------------+------+------------+-------+--------+
3-
| id | token | name | description | image | info_updates | message_sequence | read | accessible | write | upload |
4-
+----+------------+-------------------+-------------+-------+--------------+------------------+------+------------+-------+--------+
5-
| 1 | round-room | A spherical room! | NULL | NULL | 1 | 0 | 1 | 1 | 1 | 1 |
6-
| 2 | sudoku | Sudoku lovers | NULL | 3 | 2 | 1 | 1 | 1 | 1 | 1 |
7-
+----+------------+-------------------+-------------+-------+--------------+------------------+------+------------+-------+--------+
2+
+----+------------+-------------------+-------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
3+
| id | token | name | description | image | active_users | info_updates | message_sequence | read | accessible | write | upload |
4+
+----+------------+-------------------+-------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
5+
| 1 | round-room | A spherical room! | NULL | NULL | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
6+
| 2 | sudoku | Sudoku lovers | NULL | 3 | 0 | 2 | 1 | 1 | 1 | 1 | 1 |
7+
+----+------------+-------------------+-------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
88

99
room_import_hacks:
1010
+------+-------------------+--------------------+

contrib/upgrade-tests/v0.2.0-expected.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
rooms:
2-
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+------------------+------+------------+-------+--------+
3-
| id | token | name | description | image | info_updates | message_sequence | read | accessible | write | upload |
4-
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+------------------+------+------------+-------+--------+
5-
| 1 | gibberish | Gibberish 🥄 | Delivering your daily dose of gibberish. | 3 | 3 | 7 | 1 | 1 | 1 | 1 |
6-
| 2 | sudoku | Sudoku | Delivering your daily dose of gib... sudoku. | 1 | 3 | 5 | 1 | 1 | 1 | 1 |
7-
| 3 | cool-room | Private room | If you're reading these posts then you're too cool for school. | NULL | 1 | 4 | 0 | 1 | 0 | 0 |
8-
| 4 | empty-room | Empty | We don't go there anymore. | NULL | 1 | 0 | 1 | 1 | 1 | 1 |
9-
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+------------------+------+------------+-------+--------+
2+
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
3+
| id | token | name | description | image | active_users | info_updates | message_sequence | read | accessible | write | upload |
4+
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
5+
| 1 | gibberish | Gibberish 🥄 | Delivering your daily dose of gibberish. | 3 | 0 | 3 | 7 | 1 | 1 | 1 | 1 |
6+
| 2 | sudoku | Sudoku | Delivering your daily dose of gib... sudoku. | 1 | 0 | 3 | 5 | 1 | 1 | 1 | 1 |
7+
| 3 | cool-room | Private room | If you're reading these posts then you're too cool for school. | NULL | 0 | 1 | 4 | 0 | 1 | 0 | 0 |
8+
| 4 | empty-room | Empty | We don't go there anymore. | NULL | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
9+
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
1010

1111
room_import_hacks:
1212
message_metadata:

contrib/upgrade-tests/v0.3.0-pg-expected.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
rooms:
2-
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+------------------+------+------------+-------+--------+
3-
| id | token | name | description | image | info_updates | message_sequence | read | accessible | write | upload |
4-
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+------------------+------+------------+-------+--------+
5-
| 1 | gibberish | Gibberish 🥄 | Delivering your daily dose of gibberish. | 2 | 3 | 10 | 1 | 1 | 1 | 1 |
6-
| 2 | sudoku | Sudoku | Delivering your daily dose of gib... sudoku. | 1 | 2 | 4 | 1 | 1 | 1 | 1 |
7-
| 3 | cool-room | Private room | If you're reading these posts then you're too cool for school. | NULL | 1 | 4 | 1 | 1 | 1 | 1 |
8-
| 4 | empty-room | Empty | We don't go there anymore. | NULL | 1 | 0 | 1 | 1 | 1 | 1 |
9-
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+------------------+------+------------+-------+--------+
2+
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
3+
| id | token | name | description | image | active_users | info_updates | message_sequence | read | accessible | write | upload |
4+
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
5+
| 1 | gibberish | Gibberish 🥄 | Delivering your daily dose of gibberish. | 2 | 0 | 3 | 10 | 1 | 1 | 1 | 1 |
6+
| 2 | sudoku | Sudoku | Delivering your daily dose of gib... sudoku. | 1 | 0 | 2 | 4 | 1 | 1 | 1 | 1 |
7+
| 3 | cool-room | Private room | If you're reading these posts then you're too cool for school. | NULL | 0 | 1 | 4 | 1 | 1 | 1 | 1 |
8+
| 4 | empty-room | Empty | We don't go there anymore. | NULL | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
9+
+----+------------+--------------+----------------------------------------------------------------+-------+--------------+--------------+------------------+------+------------+-------+--------+
1010

1111
room_import_hacks:
1212
message_metadata:

sogs/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def print_room(room: Room):
169169
msgs_size /= 1_000_000
170170
files_size /= 1_000_000
171171

172-
active = [room.active_users(x * 86400) for x in (7, 14, 30)]
172+
active = [room.active_users_last(x * 86400) for x in (7, 14, 30)]
173173
m, a, hm, ha = room.get_all_moderators()
174174
admins = len(a) + len(ha)
175175
mods = len(m) + len(hm)

sogs/cleanup.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ def prune_room_activity():
8484

8585
if count > 0:
8686
app.logger.info("Prune {} old room activity records".format(count))
87+
88+
query(
89+
"""
90+
UPDATE rooms SET active_users = (
91+
SELECT COUNT(*) FROM room_users WHERE room = rooms.id AND last_active >= :since)
92+
""",
93+
since=time.time() - config.ROOM_DEFAULT_ACTIVE_THRESHOLD,
94+
)
95+
8796
return count
8897

8998

sogs/migrations/new_columns.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def migrate(conn, *, check_only):
1515
'whisper': 'INTEGER REFERENCES users(id)',
1616
'whisper_mods': 'BOOLEAN NOT NULL DEFAULT FALSE',
1717
'filtered': 'BOOLEAN NOT NULL DEFAULT FALSE',
18-
}
18+
},
19+
'rooms': {'active_users': 'BIGINT NOT NULL DEFAULT 0'},
1920
}
2021

2122
added = False

sogs/model/room.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class Room:
4545
new/edited/deleted messages.
4646
info_updates - counter on room metadata that is automatically incremented whenever room
4747
metadata (name, description, image, etc.) changes for the room.
48+
active_users - count of the number of active users in the past
49+
config.ROOM_DEFAULT_ACTIVE_THRESHOLD seconds.
4850
default_read - True if default user permissions includes read permission
4951
default_accessible - True if default user permissions include accessible permission
5052
default_write - True if default user permissions includes write permission
@@ -92,6 +94,7 @@ def _refresh(self, *, id=None, token=None, row=None, perms=False):
9294
self.created,
9395
self.message_sequence,
9496
self.info_updates,
97+
self.active_users,
9598
) = (
9699
row[c]
97100
for c in (
@@ -103,6 +106,7 @@ def _refresh(self, *, id=None, token=None, row=None, perms=False):
103106
'created',
104107
'message_sequence',
105108
'info_updates',
109+
'active_users',
106110
)
107111
)
108112
self._default_read, self._default_accessible, self._default_write, self._default_upload = (
@@ -374,11 +378,15 @@ def default_upload(self, upload: bool):
374378
query("UPDATE rooms SET upload = :upload WHERE id = :r", r=self.id, upload=upload)
375379
self._refresh(perms=True)
376380

377-
def active_users(self, cutoff=config.ROOM_DEFAULT_ACTIVE_THRESHOLD):
381+
def active_users_last(self, cutoff: float):
378382
"""
379-
Queries the number of active users in the past `cutoff` seconds. Defaults to
380-
config.ROOM_DEFAULT_ACTIVE_THRESHOLD. Note that room activity records are periodically
381-
removed, so going beyond config.ROOM_ACTIVE_PRUNE_THRESHOLD days is useless.
383+
Queries the number of active users in the past `cutoff` seconds. This is like the
384+
`active_users` property except that it always queries for the instantaneous value
385+
(`active_users` is only updated every few seconds in sogs.cleanup), and supports values
386+
other than the default activity threshold.
387+
388+
Note that room activity records are periodically removed, so specifying a cutoff above
389+
config.ROOM_ACTIVE_PRUNE_THRESHOLD days is useless.
382390
"""
383391

384392
return query(

sogs/routes/legacy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def legacy_serve_room_image(room):
137137
def legacy_member_count():
138138
user, room = legacy_check_user_room(accessible=True)
139139

140-
return jsonify({"status_code": http.OK, "member_count": room.active_users()})
140+
return jsonify({"status_code": http.OK, "member_count": room.active_users})
141141

142142

143143
@legacy.post("/claim_auth_token")

sogs/routes/rooms.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def get_room_info(room):
2424
'info_updates': room.info_updates,
2525
'message_sequence': room.message_sequence,
2626
'created': room.created,
27-
'active_users': room.active_users(),
27+
'active_users': room.active_users,
2828
'active_users_cutoff': int(config.ROOM_DEFAULT_ACTIVE_THRESHOLD),
2929
'moderators': mods,
3030
'admins': admins,
@@ -722,7 +722,7 @@ def poll_room_info(room, info_updated):
722722

723723
result = {
724724
'token': room.token,
725-
'active_users': room.active_users(),
725+
'active_users': room.active_users,
726726
'read': room.check_read(g.user),
727727
'write': room.check_write(g.user),
728728
'upload': room.check_upload(g.user),

0 commit comments

Comments
 (0)