Skip to content

Handle restart events #1271

Open
Open

Description

@gnprice

That's these: https://zulip.com/api/get-events#restart

Handling these mostly just means updating our record of the server's version, including zulipFeatureLevel.

Getting a new event queue

There's one other wrinkle this calls for; quoting the doc:

Clients should use this event to update their tracking of the server's capabilities, and to decide if they wish to get a new event queue after a server upgrade. Clients doing so must implement a random delay strategy to spread such restarts over 5 minutes or more to avoid creating a synchronized thundering herd effect.

The case where getting a new event queue is necessary on a timescale anything like 5 minutes is where the existing data we have from the server would have a different, wrong, meaning when interpreted in terms of the new feature level.

That's pretty uncommon. With rare exceptions we're able to avoid conditioning directly on the feature level to interpret the data we get from the server — instead, we look at the data directly, and it speaks for itself as to whether it's in an old or new form. Most commonly, this is just a null-check: if some field is null (corresponding usually to a property being absent in the original JSON), the data came from a server that didn't provide that feature and we just carry on without.

(On the other hand we condition on the feature level all the time for determining what data we send to the server, and in what form.)

Concretely, I just scanned through all the places the app currently conditions on the feature level (with a grep for "zulipFeatureLevel" — it's very helpful here that we have a consistent convention of using that name for variables, parameters, etc. that represent Zulip feature levels), and I think we currently have just one example:

  String? _getDisplayEmailFor(User user, {required PerAccountStore store}) {
    if (store.account.zulipFeatureLevel >= 163) { // TODO(server-7)
      // A non-null value means self-user has access to [user]'s real email,
      // while a null value means it doesn't have access to the email.
      // Search for "delivery_email" in https://zulip.com/api/register-queue.
      return user.deliveryEmail;

If the old value of zulipFeatureLevel was less than 163 and the new value is at least 163 (or I guess vice versa), then this method would give wrong results when using the new feature level to interpret the old data. That would cause the profile screen (and with #913 / #995 the user autocomplete results) to show no email in cases where it should show an email. So in that case we should replace the event queue.

I also just scanned the API changelog entries currently published for 10.0 (so 280 up through 327), and I don't believe any of them would fall into this category.

Getting a new event queue, in the future

There's another reason we'll have in the future to get a new event queue: for many kinds of server features, as long as the data the app has is from an old server version that didn't have the feature, the app won't be offering the feature.

For example, just scanning the latest changelog entries on https://zulip.com/api/changelog right now: out of the 10 latest entries (feature levels 318 through 327), I count 4 (namely 321, 323, 324, 325) that mean (a) new information is provided, (b) in the responses to registerQueue or other endpoints whose data we save, (c) where without that information the app can't offer some feature that the server now supports. (Plus 2 more, namely 318 and 327, which do the same but with information that's only for the web app.) So about half of new feature levels.

After one of those upgrades, it's pretty OK if the app doesn't immediately offer the feature within minutes of the server being upgraded. The app will naturally get fresh data the next time it makes a new event queue, which it will do after the app is killed and restarted, but also after the device has been asleep for 10 minutes so that the server has expired the old event queue. That makes it unlikely today to have the app run on a single event queue for more than an hour or two, and nearly impossible to do overnight.

But eventually in the future we intend to have the app keep around server data for a longer period, with a long-lived event queue. See the user-facing goal:

and some technical discussion:

When that's done, the app might go for days or weeks without loading all the server data from scratch.

And then at that timescale, if there has been an upgrade that means there's new data to be had which wasn't available before, we're going to want to take explicit action to get it rather than just wait. So in conjunction with #477 and a long-lived event queue, we're probably going to want to make a fresh event queue in response to any restart event that advances zulipFeatureLevel. We can do it with a random delay over like an hour (well above the 5-minute minimum in the quoted docs), to be kind to the server; there's no rush.

Activity

  1. added
    a-apiImplementing specific parts of the Zulip server API
    on Jan 10, 2025
  2. added this to the M5: Launch milestone on Jan 10, 2025
  3. gnprice commented on Jan 10, 2025

    @gnprice
    MemberAuthor

    There's one other wrinkle this calls for

    Pragmatically, I think we will skip this wrinkle.

    It's pretty tolerable if sometimes right after a server upgrade the email addresses of other users aren't shown when they should be; key mitigating factors include that (a) it won't last long, for the reasons discussed in the last section above; (b) the upgrade in question was part of Zulip Server 7.0, which came out in 2023-05 more than a year and a half ago, so we no longer officially support any of the server versions such upgrades would be coming from. (Nor do we support 7.0 itself; but we do support 7.3, 7.4, and 7.5, as they're within the 18-month window, and there's no API difference within the 7.x series.)

    That means the scope of this issue is just to update our record of the server's version, including its feature level.

    We'll still need to make a fresh event queue in the future when we have long-lived queues, #477 / zulip/zulip-mobile#3916.

  4. gnprice commented on Oct 4, 2025

    @gnprice
    MemberAuthor

    There's one other wrinkle this calls for […] where the existing data we have from the server would have a different, wrong, meaning when interpreted in terms of the new feature level.

    That's pretty uncommon. […] Concretely, I just scanned through all the places the app currently conditions on the feature level […] and I think we currently have just one example:

    I just repeated this scan (as of 6adc9c3), and found no examples. (The FL-163 condition was removed in 0900820, after we dropped support for servers that old.)

    If we ever find ourselves adding a condition like this, we can add a short-fused make-fresh-queue response then. (Hopefully we'll just avoid introducing such things in the API, as we've successfully done with such rare exceptions in the past.)

    Otherwise, what we'll do upon a restart event is:

    • update our record of the server's version, including its feature level;
    • make a fresh event queue with a random delay spread over a long period, like 1 hour, for the reasons at the end of the issue description.
  5. added
    a-modelImplementing our data model (PerAccountStore, etc.)
    on Oct 4, 2025
  6. modified the milestones: M7: 2025Q4, M8: 2026Q1 on Oct 17, 2025
  7. gnprice commented on Nov 12, 2025

    @gnprice
    MemberAuthor

    make a fresh event queue with a random delay spread over a long period, like 1 hour

    Or potentially shorter (down to as short as 5 minutes). Chat discussion: #api design > mobile re-registration after server version update @ 💬

  8. gnprice commented on Jan 6, 2026

    @gnprice
    MemberAuthor
    • make a fresh event queue with a random delay spread over a long period

    We should also do this in another situation: when we had an error in parsing or applying an event from the server. Currently we make a fresh event queue in that situation, and have a random backoff, but the backoff starts out small and escalates on successive retries. That's useful if a single client finds itself retrying repeatedly… but another possible scenario is that an unparseable or bug-triggering event gets sent to all the users in a large realm at once, and currently that would cause a thundering herd. See #api design > stream deletion events @ 💬 and #api design > stream deletion events @ 💬.

  9. modified the milestones: M8: 2026Q1, M9: 2026Q2 on Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    a-apiImplementing specific parts of the Zulip server APIa-modelImplementing our data model (PerAccountStore, etc.)

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions