mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 05:23:35 +00:00
Migrate all `ids` of anything which does not have a foreign key from the Message or UserMessage table (and would thus require walking those) to be `bigint`. This is done by removing explicit `BigAutoField`s, trading them for explicit `AutoField`s on the tables to not be migrated, while updating `DEFAULT_AUTO_FIELD` to the new default. In general, the tables adjusted in this commit are small tables -- at least compared to Messages and UserMessages. Many-to-many tables without their own model class are adjusted by a custom Operation, since they do not automatically pick up migrations when `DEFAULT_AUTO_FIELD` changes[^1]. Note that this does multiple scans over tables to update foreign keys[^2]. Large installs may wish to hand-optimize this using the output of `./manage.py sqlmigrate` to join multiple `ALTER TABLE` statements into one, to speed up the migration. This is unfortunately not possible to do generically, as constraint names may differ between installations. This leaves the following primary keys as non-`bigint`: - `auth_group.id` - `auth_group_permissions.id` - `auth_permission.id` - `django_content_type.id` - `django_migrations.id` - `otp_static_staticdevice.id` - `otp_static_statictoken.id` - `otp_totp_totpdevice.id` - `two_factor_phonedevice.id` - `zerver_archivedmessage.id` - `zerver_client.id` - `zerver_message.id` - `zerver_realm.id` - `zerver_recipient.id` - `zerver_userprofile.id` [^1]: https://code.djangoproject.com/ticket/32674 [^2]: https://code.djangoproject.com/ticket/24203
79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
import hashlib
|
|
from typing import Dict
|
|
|
|
from django.conf import settings
|
|
from django.db import models
|
|
from typing_extensions import override
|
|
|
|
from zerver.lib import cache
|
|
from zerver.lib.cache import cache_with_key
|
|
|
|
|
|
class Client(models.Model):
|
|
MAX_NAME_LENGTH = 30
|
|
id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")
|
|
name = models.CharField(max_length=MAX_NAME_LENGTH, db_index=True, unique=True)
|
|
|
|
@override
|
|
def __str__(self) -> str:
|
|
return self.name
|
|
|
|
def default_read_by_sender(self) -> bool:
|
|
"""Used to determine whether a message was sent by a full Zulip UI
|
|
style client (and thus whether the message should be treated
|
|
as sent by a human and automatically marked as read for the
|
|
sender). The purpose of this distinction is to ensure that
|
|
message sent to the user by e.g. a Google Calendar integration
|
|
using the user's own API key don't get marked as read
|
|
automatically.
|
|
"""
|
|
sending_client = self.name.lower()
|
|
|
|
return (
|
|
sending_client
|
|
in (
|
|
"zulipandroid",
|
|
"zulipios",
|
|
"zulipdesktop",
|
|
"zulipmobile",
|
|
"zulipelectron",
|
|
"zulipterminal",
|
|
"snipe",
|
|
"website",
|
|
"ios",
|
|
"android",
|
|
)
|
|
or "desktop app" in sending_client
|
|
# Since the vast majority of messages are sent by humans
|
|
# in Zulip, treat test suite messages as such.
|
|
or (sending_client == "test suite" and settings.TEST_SUITE)
|
|
)
|
|
|
|
|
|
get_client_cache: Dict[str, Client] = {}
|
|
|
|
|
|
def clear_client_cache() -> None: # nocoverage
|
|
global get_client_cache
|
|
get_client_cache = {}
|
|
|
|
|
|
def get_client(name: str) -> Client:
|
|
# Accessing KEY_PREFIX through the module is necessary
|
|
# because we need the updated value of the variable.
|
|
cache_name = cache.KEY_PREFIX + name[0 : Client.MAX_NAME_LENGTH]
|
|
if cache_name not in get_client_cache:
|
|
result = get_client_remote_cache(name)
|
|
get_client_cache[cache_name] = result
|
|
return get_client_cache[cache_name]
|
|
|
|
|
|
def get_client_cache_key(name: str) -> str:
|
|
return f"get_client:{hashlib.sha1(name.encode()).hexdigest()}"
|
|
|
|
|
|
@cache_with_key(get_client_cache_key, timeout=3600 * 24 * 7)
|
|
def get_client_remote_cache(name: str) -> Client:
|
|
(client, _) = Client.objects.get_or_create(name=name[0 : Client.MAX_NAME_LENGTH])
|
|
return client
|