Simplify and speed up stream deactivation.

This is a fairly risky, invasive change that speeds up
stream deactivation by no longer sending subscription/remove
events for individual subscribers to all of the clients who
care about a stream.  Instead, we let the client handle the
stream deactivation on a coarser level.

The back end changes here are pretty straightforward.

On the front end we handle stream deactivations by removing the
stream (as needed) from the streams sidebar and/or the stream
settings page.  We also remove the stream from the internal data
structures.

There may be some edge cases where live updates don't handle
everything, such as if you are about to compose a message to a
stream that has been deactivated.  These should be rare, as admins
generally deactivate streams that have been dormant, and they
should be recoverable either by getting proper error handling when
you try to send to the stream or via reload.
This commit is contained in:
Steve Howell
2017-02-15 08:38:44 -08:00
committed by Tim Abbott
parent 465a765cb0
commit b9ec2545bb
4 changed files with 42 additions and 28 deletions

View File

@@ -420,8 +420,8 @@ class StreamAdminTest(ZulipTestCase):
return stream
def delete_stream(self, stream, subscribed=True):
# type: (Stream, bool) -> None
def delete_stream(self, stream):
# type: (Stream) -> None
"""
Delete the stream and assess the result.
"""
@@ -434,17 +434,15 @@ class StreamAdminTest(ZulipTestCase):
result = self.client_delete('/json/streams/' + str(stream_id))
self.assert_json_success(result)
deletion_events = [e['event'] for e in events if e['event']['type'] == 'subscription']
if subscribed:
self.assertEqual(deletion_events[0], dict(
op='remove',
type='subscription',
subscriptions=[{'name': active_name, 'stream_id': stream.id}]
))
else:
# You could delete the stream, but you weren't on it so you don't
# receive an unsubscription event.
self.assertEqual(deletion_events, [])
# We no longer send subscription events for stream deactivations.
sub_events = [e for e in events if e['event']['type'] == 'subscription']
self.assertEqual(sub_events, [])
stream_events = [e for e in events if e['event']['type'] == 'stream']
self.assertEqual(len(stream_events), 1)
event = stream_events[0]['event']
self.assertEqual(event['op'], 'delete')
self.assertEqual(event['streams'][0]['stream_id'], stream.id)
with self.assertRaises(Stream.DoesNotExist):
Stream.objects.get(realm=get_realm("zulip"), name=active_name)
@@ -498,7 +496,7 @@ class StreamAdminTest(ZulipTestCase):
"""
pub_stream = self.set_up_stream_for_deletion(
"pubstream", subscribed=False)
self.delete_stream(pub_stream, subscribed=False)
self.delete_stream(pub_stream)
priv_stream = self.set_up_stream_for_deletion(
"privstream", subscribed=False, invite_only=True)