diff --git a/docs/concepts.rst b/docs/concepts.rst index a5b43b4..64d9cad 100644 --- a/docs/concepts.rst +++ b/docs/concepts.rst @@ -13,7 +13,7 @@ And, beyond that, there are plenty of non-critical tasks that applications could easily offload until after a response has been sent - like saving things into a cache or thumbnailing newly-uploaded images. -Channels changes the way Django runs to be "event oriented" - rather than +It changes the way Django runs to be "event oriented" - rather than just responding to requests, instead Django responds to a wide array of events sent on *channels*. There's still no persistent state - each event handler, or *consumer* as we call them, is called independently in a way much like a @@ -26,7 +26,7 @@ Let's look at what *channels* are first. What is a channel? ------------------ -The core of Channels is, unsurprisingly, a datastructure called a *channel*. +The core of the system is, unsurprisingly, a datastructure called a *channel*. What is a channel? It is an *ordered*, *first-in first-out queue* with *message expiry* and *at-most-once delivery* to *only one listener at a time*. diff --git a/docs/deploying.rst b/docs/deploying.rst index 974c135..79f9a64 100644 --- a/docs/deploying.rst +++ b/docs/deploying.rst @@ -4,9 +4,9 @@ Deploying Deploying applications using Channels requires a few more steps than a normal Django WSGI application, but it's not very many. -Firstly, remember that even if you have Channels installed, it's an entirely -optional part of Django. If you leave a project with the default settings -(no ``CHANNEL_BACKENDS``), it'll just run and work like a normal WSGI app. +Firstly, remember that it's an entirely optional part of Django. +If you leave a project with the default settings (no ``CHANNEL_LAYERS``), +it'll just run and work like a normal WSGI app. When you want to enable channels in production, you need to do three things: @@ -112,7 +112,7 @@ cluster on the backend, see :ref:`wsgi-to-asgi`. If you want to support WebSockets, long-poll HTTP requests and other Channels features, you'll need to run a native ASGI interface server, as the WSGI specification has no support for running these kinds of requests concurrently. -Channels ships with an interface server that we recommend you use called +We ship with an interface server that we recommend you use called `Daphne `_; it supports WebSockets, long-poll HTTP requests, HTTP/2 *(soon)* and performs quite well. Of course, any ASGI-compliant server will work! @@ -164,7 +164,7 @@ workers. As long as the new code is session-compatible, you can even do staged rollouts to make sure workers on new code aren't experiencing high error rates. There's no need to restart the WSGI or WebSocket interface servers unless -you've upgraded your version of Channels or changed any settings; +you've upgraded the interface server itself or changed any Django settings; none of your code is used by them, and all middleware and code that can customize requests is run on the consumers. diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 8968377..aa83555 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -19,8 +19,8 @@ with a WSGI-based Django, and your views and static file serving (from As a very basic introduction, let's write a consumer that overrides the built-in handling and handles every HTTP request directly. This isn't something you'd -usually do in a project, but it's a good illustration of how Channels -underlies even core Django - it's less of an addition and more adding a whole +usually do in a project, but it's a good illustration of how channels +underlie even core Django - it's less of an addition and more adding a whole new layer under the existing view layer. Make a new project, a new app, and put this in a ``consumers.py`` file in the app:: @@ -279,7 +279,7 @@ see :doc:`backends` for more. The second thing, once we have a networked channel backend set up, is to make sure we're running an interface server that's capable of serving WebSockets. -Luckily, installing Channels will also install ``daphne``, an interface server +To solve this, Channels comes with ``daphne``, an interface server that can handle both HTTP and WebSockets at the same time, and then ties this in to run when you run ``runserver`` - you shouldn't notice any difference from the normal Django ``runserver``, though some of the options may be a little @@ -471,7 +471,7 @@ Django session ID as part of the URL, like this:: socket = new WebSocket("ws://127.0.0.1:9000/?session_key=abcdefg"); You can get the current session key in a template with ``{{ request.session.session_key }}``. -Note that Channels can't work with signed cookie sessions - since only HTTP +Note that this can't work with signed cookie sessions - since only HTTP responses can set cookies, it needs a backend it can write to to separately store state. @@ -479,7 +479,7 @@ store state. Routing ------- -Channels' ``routing.py`` acts very much like Django's ``urls.py``, including the +The ``routing.py`` file acts very much like Django's ``urls.py``, including the ability to route things to different consumers based on ``path``, or any other message attribute that's a string (for example, ``http.request`` messages have a ``method`` key you could route based on). @@ -508,7 +508,7 @@ routing our chat from above:: include(http_routing), ] -Channels will resolve the routing in order, short-circuiting around the +The routing is resolved in order, short-circuiting around the includes if one or more of their matches fails. You don't have to start with the ``^`` symbol - we use Python's ``re.match`` function, which starts at the start of a line anyway - but it's considered good practice. @@ -624,7 +624,7 @@ same effect if someone tried to request a view before the login view had finishe processing, but there you're not expecting that page to run after the login, whereas you'd naturally expect ``receive`` to run after ``connect``. -Channels has a solution - the ``enforce_ordering`` decorator. All WebSocket +Channels has a solution - the ``enforce_ordering`` decorator. All WebSocket messages contain an ``order`` key, and this decorator uses that to make sure that messages are consumed in the right order, in one of two modes: @@ -695,6 +695,6 @@ to manage logical sets of channels, and how Django's session and authentication systems easily integrate with WebSockets. We recommend you read through the rest of the reference documentation to see -all of what Channels has to offer; in particular, you may want to look at +more about what you can do with channels; in particular, you may want to look at our :doc:`deploying` and :doc:`scaling` resources to get an idea of how to design and run apps in production environments. diff --git a/docs/reference.rst b/docs/reference.rst index adc2d1d..aaa99e2 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -6,9 +6,10 @@ Reference Consumers --------- -When you configure channel routing, Channels expects the object assigned to -a channel to be a callable that takes exactly one positional argument, here -called ``message``. This is a :ref:`message object `. +When you configure channel routing, the object assigned to a channel +should be a callable that takes exactly one positional argument, here +called ``message``, which is a :ref:`message object `. A consumer +is any callable that fits this definition. Consumers are not expected to return anything, and if they do, it will be ignored. They may raise ``channels.exceptions.ConsumeLater`` to re-insert diff --git a/docs/testing.rst b/docs/testing.rst index d10a4c6..20c7732 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -6,7 +6,7 @@ realize that you can't use the standard Django test client to submit fake HTTP requests - instead, you'll need to submit fake Messages to your consumers, and inspect what Messages they send themselves. -Channels comes with a ``TestCase`` subclass that sets all of this up for you, +We provide a ``TestCase`` subclass that sets all of this up for you, however, so you can easily write tests and check what your consumers are sending. diff --git a/patchinator.py b/patchinator.py index 9c5eb34..4064013 100644 --- a/patchinator.py +++ b/patchinator.py @@ -142,6 +142,17 @@ docs_transforms = global_transforms + [ Replacement(r":doc:`([\w\d\s]+) `", r"`\1 `_"), Replacement(r"\n\(.*installation>`\)\n", r""), Replacement(r":doc:`installed Channels correctly `", r"added the channel layer setting"), + Replacement(r"Channels", r"channels"), + Replacement(r"Started with channels", r"Started with Channels"), + Replacement(r"Running with channels", r"Running with Channels"), + Replacement(r"channels consumers", r"channel consumers"), + Replacement(r"channels' design", r"The channels design"), + Replacement(r"channels is being released", r"Channels is being released"), + Replacement(r"channels is", r"channels are"), + Replacement(r"channels provides a", r"Channels provides a"), + Replacement(r"channels can use", r"Channels can use"), + Replacement(r"channels Concepts", r"Channels Concepts"), + Replacement(r"channels works", r"channels work"), ]