Use python coroutine to design a back-end program for voice communication

Source: Internet
Author: User

Some summary in development is a bit messy.

This section describes how to design a tsapi program if you use a Python coroutine. I have accumulated some experience in the final Scheduling design and finally formed a framework. In this framework, new functions can be easily added, so that other employees will not be afraid of the Python coroutine.


1. the main part of the entire framework is the call module, which is mainly responsible for controlling the call process. It aggregates all the calls to asapi into one module, which can encapsulate modules for future replacement.
2. The interaction object between the call module and the upper-layer Module I originally considered using the user number, but considering the convenience, and so on, it must be based on the assumption that all user numbers must be unique identifiers: it is not conducive to later maintenance. Therefore, the user and meet objects in the asobj module are used as interaction objects. We recommend that you use a combination of User and meet classes before considering inheritance.
3. The poc server uses a callinfo mechanism, that is, all users in a stable State have a callinfo to record their current state. Originally, I didn't want to use such an object to record it, because different relations have different callinfo definitions, and callinfo will eventually become more popular. Without callinfo, coroutine is required to be able to manage the full lifecycle of a process, including the beginning and the end. In this way, it will be difficult to deal with the relationship between the two processes. Therefore, you still need to use callinfo. However, there are only two callinfo, p2p and meetcallinfo.
4. Consider A Business Process: A, B, and C users are performing A call process, such as transfer, c is ringing, but not yet connected. In this case, another higher-priority process needs to pull C into the new process. It is recommended that c be able to initiate a call without hanging up, and the original process can be processed normally. To implement this function, you need to add a user_man module for user management. All outbound calls to users call the interface of this module for outbound calls. Each outbound call applies for a new coroutine. After the coroutine ends, it returns the original coroutine for subsequent operations. If there is a new process to operate this user when the call fails, the original coroutine is stopped, and the new coroutine is directly processed after the makecall coroutine is completed.
5. How can a coroutine send a message to the coroutine in the processing process and let the coroutine perform different processing? In this case, a method similar to golang is used. Each coroutine provides a channel for external communication, and all coroutines Use channel messages. Yes, but after implementation, the entire coroutine mechanism will be complicated. Because each coroutine has a stack, the original stack must be stopped for each message processing, and the original stack must be returned after processing. If the coroutine interface is called during message processing, the processing of stacks and messages will be in disorder. Therefore, for similar requirements, the following mechanism is used: 1) if exceptions occur during coroutine processing and the coroutine needs to be terminated, different types of exceptions can be sent to the coroutine through the throw interface of the coroutine.
2) if a user is pulled by another coroutine to handle other tasks during the process, the user does not affect the original process after leaving, therefore, the original process cannot be terminated (if it is to be terminated, it will be handled ). If the original process needs to process this user, it may conflict with the current process. For example, if you want to resume a call after the force-insertion end user is maintained by the last user, how can the user be properly handled when the user has been pulled into other processing processes. The following solution: 1. A user only runs one coroutine for processing. Each coroutine starts, the user's lock (or sign) must be set. After the lock is set, other coroutines cannot process this user unless they are forcibly unlocked. Disadvantage: It increases programming complexity. A user must be set before being used by the coroutine, and should be unlocked when not used. Error-prone. To determine the scheme, use the Lock Scheme: Lock the coroutine at the beginning, and unlock the coroutine after the coroutine ends. Only the coroutine that locks the user can process the user. 2. the cancellation and compensation functions should also be adjusted: Currently there is no lock solution. Now we need to add a lock. The compensation is because the manual process is not used to lock this user, then, you cannot perform operations on users. 3. Final Solution: A large module is responsible for maintaining all users and implementing the user's makecall interface (all makecall must be taken here ). Before implementing all the as call control interfaces and call control operations, you must determine whether the user is controlled by the current operation coroutine. All compensation operations must also be determined by the coroutine to determine whether to control the user. The user was originally controlled by a coroutine. to be controlled by another coroutine, you need to know all the statuses of the User: The sound is stopped, the recording is stopped, and the venue is left. In short, restore to the original status of the call. If it is out of a stable State and is not in Ctrip, it will be handled separately. Ultimate Solution: Set the coroutine status for each call control interface, and then process different events in different States, this is the most tedious method. But it is also the most obvious and simple method.
6. How can I end a user with a host connection or call? There are two types of users: active incoming and outgoing calls. How should these users hook up? You can choose the upper-layer services based on your business needs, or hook up with the coroutine compensation, or wait for the operator to operate or use a mechanism similar to garbage collection, if no call is made or the coroutine is on the user, garbage collection is automatically performed. -- Check again based on the business.
The first step is to move users out of the original process. Step 2: determine the user status. If a call has been made, the server will be suspended. If the call is in the new call schedule, the new schedule will be stopped.
Each process selects different processes for users based on different situations. At the same time, we also consider increasing the garbage collection protection.
7. During the encoding process, the original Greenlet mode is found: the parent coroutine calls the child coroutine. After the child coroutine is processed, switch to the parent coroutine for processing. This mode is very error-prone because, in the process of coroutine interaction, it is easy to make an error: the parent coroutine wants to wait, but cannot wait for the running result of the Child coroutine. Therefore, consider processing the coroutine according to the handling method of the go coroutine.
8. reconsider a module to manage all users: Call, host, and seize.
The kill of the coroutine has a problem: the coroutine may have ended but is not processed in the coroutine task list.
9. During User preemption, you must record the users currently being snatched in a unified portal. If there is a new process to seize the same user, the previous preemption will be stopped. A new process is provided after the user preemptible. Preemption is all the call operations of the clear user: (recording, playing, connection, meeting, etc.) until the call passes, there is no operation status. One problem is that, if the user is performing operations, such as connect, it cannot be canceled. This can be canceled only when the coroutine is canceled. Coro operations must be performed if you want to wait for a response to send messages between the coroutines. Call preemption: You must stop the coroutine before performing operations. Because canceling the coroutine may affect new operations.The session of all processes is applied when the process is created. It is used to save the information of the process and report the preemption processing function of each user.

Conclusion: It is difficult to solve the problem of State and Data Synchronization by using the python coroutine to simplify process development. If there is little association between coroutines, it is relatively simple. However, the challenges faced by our company are not performance, but business logic complexity, especially process interaction between processes. This is my second attempt to solve similar problems using the python coroutine. At present, it has been basically solved, but there is still room for optimization, and the complexity of some modules is still relatively high.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.