Python Web Preference

    Not the first decade, a debate continues between desktop architects about whether a statefull or stateless approach is preferable, and in which cases.
    Now we are witnessing a certain trend of passing positions by statefull apologists. Not least of all, not so much the web is to blame for this, as is the banal HTTP, which has deservedly occupied the niche of the “universal protocol for everything”. Moreover, the ability to transfer cookies has very little effect on its stateless nature.

    But what can HTTP offer us if you need to create an interactive application on the web? In order to achieve the “reactivity” of an offline statefull application, the classic version with constant polling of the server status by short AJAX timer requests is clearly not enough. HTML5 brings us WebSockets technology to solve this problem. But you need to work "here and now" on all browsers released in the current millennium.

    Comet technology comes to the rescue, with the help of which we made an attempt to implement a browser-based Russian preference with instant reaction to events.

    So, get acquainted. Club of intellectual games "Trelljaz"
    trellis-club.com

    Trellis


    Framework selection


    Two candidates were cast for the role of a low-level asynchronous library for the project.
    Twisted and Tornado. Both have their pros and cons, all of which Tornado defeated. He is significantly inferior to his opponent in features, and what is most unpleasant, he is not able to make asynchronous requests to the database out of the box, but ... sane html-templates, resource managers, built-in authorization tools on openid servers, impressive performance, very convenient and simple interface for the application programmer, they hung the cup on the other side.

    The problem with the number of concurrent open connections


    Looking at the simple and understandable examples from the Tornado delivery, it becomes clear how to write interactive things very quickly like a simple chat. One wants to immediately make several independent connections listening to different types of events. But, unfortunately, the reality is that such a scheme does not work. The reason for this is the old browsers that can not handle more than two AJAX requests at the same time.

    In other words, if we want to do something more complicated than banal chat, we will have to come up with and implement our own high-level message delivery protocol working on top of JSON.

    Authorization and Authentication


    Novice developers often confuse the two. But there is a fundamental difference between them. Roughly speaking, authentication is a procedure for determining whether this is a user who pretends to be himself, and authorization, respectively, is a procedure for granting certain rights to a user who has already passed the authentication procedure.

    In the current version of the server, authorization is abolished as unnecessary. All players are equal and are not divided into any classes.

    Authentication is completely at the mercy of the OpenID protocol. Tornado includes authentication classes through Facebook, Gmail, and other popular services. There is no problem adding access to authentication services of the same LiveJournal.

    In addition to simplifying the entry for players (the tedious registration procedure with inventing passwords and simply confirming email is no longer needed), this scheme is safer for players. The administration will not know any player passwords, and at the same time, the server is not threatened by the invasion of anonymous vandals.

    Game cycle


    The general scheme is as follows. The interactive page makes a “long” AJAX request. The server for each game table holds a pool of these requests and waits for events. An event can be anything. The player clicked on the card, wrote a chat message, a timeout occurred, the bullet count changed, etc. When the event arrives in the queue, the server closes the connection of all listeners with the answer what exactly happened. The client page receives the message and decides what to do next. She can take the data from the message and redraw some of her parts, she can make a “short” AJAX request for additional data, she can redirect to another page, but in the end she again sends a “long” AJAX request that waits for the next event, and the cycle resumes.

    It often happens that several events occurred on the server at once, and for performance reasons, our protocol should be able to send events not only one at a time, but also several at once in one request. For example, a player made a move, this move was the last, and you need to immediately calculate the game. In this case, the server will send both events to the table listeners in one iteration.

    Web site


    In addition to directly gaming tables, the project needs a website with a main page, rules, blogs, forums, statistics and more. It was decided not to separate the gaming room and the website into independent entities, and integrally integrate the website into the server.

    Given that with such an organization, a site has access to all operational server caches (including online player caches), this gives certain performance advantages and simplifies the task of programming the site’s functionality as much as possible.

    Database


    In single-threaded non-blocking servers, it is very important that there are no lengthy synchronous operations when generating a response. Connecting to a database and synchronously waiting for SQL queries to complete is a very time-consuming operation.

    This is usually bypassed using asynchronous database queries. Of the popular drivers, this mode of operation is supported, for example, by psycopg2. You can go further and use the services of “adult” ORMs like SQL Alchemy, which can add an asynchronous layer for almost any driver.

    An alternative is to use a database to a minimum. Game processes entirely occur in the server memory. All statistics for viewing are cached wherever possible. After the calculation, information about the game played is reset to the database only once. Sessions in the generally accepted understanding of web applications in the database are not needed at all with this model of building a server. The main page of the website does not create a single sql query. Everything is taken from operational caches.

    Thus, we maintain the simplicity of synchronous programming, reduce the list of dependencies, and an additional bonus is protection against DDOS. Queries from unlogged players, in principle, do not have access to resources that can generate SQL queries.

    Total information


    In addition to the operational data of each table, the server stores data that should be accessible from any module. This, for example, a general list of players online, caches of the most recently viewed games, a database pool, and more. Data of this kind are collected in one module. Here it would seem. Finally, the Singleton pattern will find at least some use. But not so simple. Firstly, timeouts from the threading system module are actively used inside the server. And this means that all our caches must be thread safe. That is, calls changing their contents will have to be wrapped in safe sections. On the other hand, we need an easy-to-use test mode in which the general data module should work in a completely different way. Therefore, Singleton goes where it belongs to him, and Facade comes to his position.

    Timeouts


    The timeout system is significantly simplified compared to existing native clients. The player presses the “set table” button. At the same time, the table immediately switches to the “convention” state. A corresponding message is sent to all the players in this room, and they immediately see that the status of the table has changed. The cover, by means of jquery-ui, has a dialog box in which he can select game conventions and the timer ticks from above. The default is 2 minutes. If for this the cover did not decide what exactly he wants to play, the window closes and the table returns to the “free” status without any consequences for the player.

    After the table is created, it goes into the endless waiting mode for the players. Players can approach the table, watch conventions, sit down at the table, get up from the table (the seat is vacated). If the last player got up from the table, then the table is completely empty, and on it you can set another game.

    But as soon as the last player sat down at the table (third or fourth, depending on how many people have set the table), the game starts immediately without any warning. A certain time is allotted for any action of the player (its amount is determined by the person setting the table. 5 minutes by default). If a player moves away or thinks for a very long time, he is fined and the game is closed. No player standby modes or game transfers in the current server version are provided. Any problems with communication or over time lie entirely on the shoulders of the player, who, in turn, should be like at all costs.

    Lovers of Dishonesty


    The only limitation is this: The same player cannot sit down at the same table twice. There are no more restrictions. If he manages to play at two or more tables at the same time, then this is his right.

    Widely known in narrow circles, the “nalap problem” cannot be solved by technical means (anyone who needs it knows about anonymous proxies, and raising a few virtual machines is not a problem for them). In this case, deanonymity, audit, feedback system and player ratings are very important. When you play not with impersonal nicknames, but with real people who have a name and surname (provided by open-id consumer, and it is impossible to change them on the server), then in this regard everything becomes much simpler.

    What's next?


    At the moment, the server is in the status of BETA testing.
    Located at trellis-club.com

    A pleasant and addictive game.

    Also popular now: