-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix-action-id #31
fix-action-id #31
Conversation
added validation for actionID in command response
hi, I was finally able to solve the command collision problem without adding an event broker: added a mutex in the "send" and "requestList" functions.
|
The goami connection is single threaded. If you reuse a single connection between multiple threads and commands it will block other threads until one thread complete with connection. So, the easy solution is create a separate goami connection to each thread, that could overhead the asterisk server. The hard solution it's create a connection pool. I believe that what we have with your implementation partly fix that, but I'd like to suggest this Object Pool Design Pattern. keeping the fix in responses := make([]Response, 0)
for {
response, err := read(ctx, client)
if err != nil {
return nil, err
}
if response.Get("ActionID") != id {
continue
}
e := response.Get("Event")
r := response.Get("Response")
if e == event {
responses = append(responses, response)
} else if e == complete || r != "" && r != "Success" {
break
}
}
return responses, nil Suggestion: Modify your PR to just to fix the actionID (like described in the title). |
Hi, thanks for your time! |
added validation for actionID in command response (cherry picked from commit 6621655)
fix-action-id See merge request mind-framework/asterisk/goami!1
Hi there, let me know if any correction to this PR is needed. |
ami/utils.go
Outdated
b, err := command(action, id, v) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := client.Send(string(b)); err != nil { | ||
return nil, err | ||
} | ||
return read(ctx, client) | ||
for { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why a looping here ?
The ActionId, in case of included in the command, must have to be in the response.
I'd like to suggest returning a known error to be thread outside the library, for example:
var (
// ErrInvalidResponseActionID occurss when the response doesn't have the same action id
ErrInvalidResponseActionID = errors.New("invalid response action id")
)
...
response, err := read(ctx, client)
if err != nil {
return nil, err
}
if id == "" || id == response.Get("ActionID") {
return response, err
}
return nil, ErrInvalidResponseActionID
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the AMI interface is asynchronous. the response returned by the "read" function may not be the response to the executed command, but some asynchronous event returned. An example of this is the Logout command, when you run it you will receive two messages from AMI, the response to the command and a "logout" event, depending on the order in which the messages arrives will fail.
the only way I could think of to avoid this is with a loop, waiting for the response to the actionid, but it makes the actionID mandatory
added validation for actionID in command response
fixes #14
fixes #22