Opensips - How can run script route only one time when use event routing in same Dialog? - opensips

Dears,
I use Opensips 3.2
Here is my script:
store_dlg_value("is_sended_inv","0");
notify_on_event("E_UL_CONTACT_INSERT", $avp(filter), "LATE_FORKING", 45);
notify_on_event("E_UL_CONTACT_UPDATE", $avp(filter), "LATE_FORKING", 45);
...
## Handle late forking route
route[LATE_FORKING] {
# handle incoming calls for mobile devices woken up by push notifications
$var(is_sended_inv) = $dlg_val(is_sended_inv);
xlog("L_INFO", "[LATE_FORKING] [var(is_sended_inv)=$var(is_sended_inv)] New contact [$avp(uri)] registered for user [$avp(aor)], inserting new branch to ongoing call\n");
# take the contact described by the E_UL_CONTACT_INSERT
# event and inject it as a new branch into the original
# transaction
if(!$var(is_sended_inv)) {
t_inject_branches("event", "last");
xlog("L_INFO", "[LATE_FORKING] t_inject_branches event\n");
store_dlg_value("is_sended_inv","1");
}
}
When Register sent many times, t_inject_branches got called back many times, resulted in a lot of Invite sending (same CSeq number).
How can call t_inject_branches only one time when use event routing in same Dialog?
Thank you for your help.
I tried store_dlg_value

Related

How to properly configure SQS without using SNS topics in MassTransit?

I'm having some issues configuring MassTransit with SQS. My goal is to have N consumers which create N queues and each of them accept a different message type. Since I always have a 1 to 1 consumer to message mapping, I'm not interested in having any sort of fan-out behaviour. So publishing a message of type T should publish it directly to that queue. How exactly would I configure that? This is what I have so far:
services.AddMassTransit(x =>
{
x.AddConsumers(Assembly.GetEntryAssembly());
x.UsingAmazonSqs((context, cfg) =>
{
cfg.Host("aws", h =>
{
h.AccessKey(mtSettings.AccessKey);
h.SecretKey(mtSettings.SecretKey);
h.Scope($"{mtSettings.Environment}", true);
var sqsConfig = new AmazonSQSConfig() { RegionEndpoint = RegionEndpoint.GetBySystemName(mtSettings.Region) };
h.Config(sqsConfig);
var snsConfig = new AmazonSimpleNotificationServiceConfig()
{ RegionEndpoint = RegionEndpoint.GetBySystemName(mtSettings.Region) };
h.Config(snsConfig);
});
cfg.ConfigureEndpoints(context, new BusEnvironmentNameFormatter(mtSettings.Environment));
});
});
The BusEnvironmentNameFormatter class overrides KebabCaseEndpointNameFormatter and adds the environment as a prefix, and the effect is that all the queues start with 'dev', while the h.Scope($"{mtSettings.Environment}", true) line does the same for topics.
I've tried to get this working without configuring topics at all, but I couldn't get it working without any errors. What am I missing?
The SQS docs are a bit thin, but is at actually possible to do a bus.Publish() without using sns topics or are they necessary? If it's not possible, how would I use bus.Send() without hardcoding queue names in the call?
Cheers!
Publish requires the use of topics, which in the case of SQS uses SNS.
If you want to configure the endpoints yourself, and prevent the use of topics, you'd need to:
Set ConfigureConsumeTopology = false – this prevents topics from being created and connected to the receive endpoint queue.
Set PublishFaults = false – this prevents fault topics from being created when a consumer throws an exception.
Don't call Publish, because, obviously that will create a topic.
If you want to somehow establish a convention for your receive endpoint names that aligns with your ability to send messages, you could create your own endpoint name formatter that would use message types and then use those same names to call GetSendEndpoint using the queue:name short name syntax to Send messages directly to those queues.

Service-Worker stays in waiting state in Chrome

I'm working on a SPA with Vue. I'd like to update to a new service-worker when the user navigates to a specific page. A save moment to refresh, because the view of the user already changes (a pattern discussed in this video: https://youtu.be/cElAoxhQz6w)
I have an issue that sometimes (infrequently) the service-worker won't activate while calling skipWaiting. The call is made correctly, and even in Chrome I get a response that the current service-worker stops (see animated GIF), however it the same service-worker starts running again, instead of the waiting one.
After a while (1-2 minutes) the service-worker is suddenly activated. Not a situation you want, because it happens just out of the blue when the user might be in the middle of an activity.
Also when I am in this situation I can't activate the service-worker by calling skipWaiting (by doing multiple navigations) again. It's received by the service-worker but nothing happens. It stays in "waiting to activate". When I press skipWaiting in Chrome itself, it works.
I have no clue what goes wrong. Is this an issue with Chrome, workbox or something else?
Most close comes this topic: self.skipWaiting() not working in Service Worker
I use Vue.js, but I don't depend on the pwa plugin for the service-worker. I use the workbox webpack plugin.
I've edited the example code below, the minimal code probably didn't show the problem well
In main.js:
let sw = await navigator.serviceWorker.register("/service-worker.js", {
updateViaCache: "none",
});
let firstSw = false;
navigator.serviceWorker.addEventListener("controllerchange", () => {
// no need to refresh when the first sw controls the page, we solve this with clientsClaim
// this makes sure when multiple-tabs are open all refresh
if (!firstSw) {
window.location.reload();
}
});
sw.onupdatefound = () => {
const installingWorker = sw.installing;
installingWorker.onstatechange = async () => {
console.log("installing worker state-change: " + installingWorker.state);
if (installingWorker.state === "installed") {
if (navigator.serviceWorker.controller) {
firstSw = false;
// set the waiting service-worker in the store
// so we can update it and refresh the page on navigation
await store.dispatch("setWaitingSW", sw.waiting);
} else {
console.log("First sw available");
firstSw = true;
}
}
};
};
In router.js:
// after navigation to specific routes we check for a waiting service-worker.
router.afterEach(async (to) => {
if (to.name == "specificpage") {
let waitingSw = store.getters["getWaitingSW"];
if (waitingSw) {
waitingSw.postMessage("SKIP_WAITING");
// clean the store, because we might have changed our data model
await store.dispatch("cleanLocalForage");
}
}
});
In service-worker.js:
self.addEventListener("message", event => {
if (event.data === "SKIP_WAITING") {
console.log("sw received skip waiting");
self.skipWaiting();
}
});
skipWaiting() isn't instant. If there are active fetches going through the current service worker, it won't break those. If you're seeing skipWaiting() taking a long time, I'd guess you have some long-running HTTP connections holding the old service worker in place.
I'm not sure that
let sw = await navigator.serviceWorker.register("/service-worker.js", {updateViaCache: "none"});
if (sw.waiting) {
sw.waiting.postMessage("SKIP_WAITING");
}
is the code that you want in this case. Your if (sw.waiting) check is only evaluated once, and the newly registered service worker might still be in the installing state when it's evaluated. If that's the case, then sw.waiting will be false-y at the time of initial evaluation, though it may be true-thy after a small period of time.
Instead, I'd recommend following a pattern like what's demonstrated in this recipe, where you explicitly listen for a service worker to enter waiting on the registration. That example uses the workbox-window library to paper over some of the details.
If you don't want to use workbox-window, you should follow this guidance check to see if sw.installing is set after registration; if it is, listen to the statechange event on sw.installing to detect when it's 'installed'. Once that happens, sw.waiting should be set to the newly installed service worker, and at that point, you could postMessage() to it.
Ok i had a similar issue and it took me two days to find the cause.
There is a scenario where you can cause a race condition between the new service worker and the old if you request a precached asset at the exact same time you call skip waiting.
For me i was prompting the user to update to a new version and upon their confirmation i was showing a loading spinner which was a Vue SFC dynamic import which kicked off a network request to the old service worker to fetch the precached js file which basically caused both to hang and get very confused.
You can check if your having a similar issue by looking at the service worker specific network requests (Network requests button in the image below) that are happening and make sure they aren't happening the instant you're trying to skip waiting on your newer service worker.

Track event to Google TagManager inside a ServiceWorker

I'm working on a service-worker (really a firebase cloud-messaging serviceworker like this) and I would like to track each time a user receives a push on Google TagManager.
Any help on how to include the script and send tracks within a SW?
Thanks.
The Service worker runs outside the main thread and does not have
access to the Window object, meaning that it cannot access the data
layer or the ga command queue to create trackers. In short, the
actions of a service worker cannot be tracked using the normal
on-page, JavaScript-based tracking snippets. What we can do, however,
is configure our service worker to send HTTP hits directly to GA.
Here is a sample code
fetch('https://www.google-analytics.com/collect', {
method: 'post',
body: JSON.stringify({
v: 1, // Version Number
t: eventName, // Hit Type
ec: eventCategory, // Event Category
ea: eventAction, // Event Action
el: 'serviceworker' // Event Label
})
})
If you want to get into more details, I would recommend reading this article. https://builtvisible.com/google-analytics-for-pwas-tracking-offline-behaviour-and-more/

Rails: sleep until there is data to respond with (streaming + multithreading)

I am building a Rails/Javascript application which is supposed to support real-time notifications. JavaScript is:
var chat;
$(document).ready(function(){
chat = $('#chat');
chat.append('mmm');
(function poll(){
$.ajax({ url: "http://localhost:3000/get_messages", success: function(data){
//Update your dashboard gauge
chat.append(data);
}, dataType: "json", complete: poll, timeout: 30000 });
})();
});
The route:
match 'get_messages', to: 'real_time_notifs#get_messages', :via => :get
Here is the controller's method:
def get_messages
# sleep ??? will it stop the whole application?
render :json => ['message body']
end
I want that JavaScript will receive an answer only if there is something to display (for example, new message appeared in database table) without making a whole application to stop. Could you suggest how to organize get_messages method?
I need the solution which will not block the rest of application while waiting.
There are a number of ways to achieve this
Although I don't have huge experience, you should be thinking about it from another perspective (not just sending Ajax poll requests):
SSE's (Server Sent Events)
I'd recommend you use SSE's
The sent updates are not in the usual HTTP scope (uses its own mime type -- text/event-stream), which I believe means they are completely asynchronous (doesn't matter what you're doing in the app etc)
SSE's are basically done through the front-end by deploying a JS listener. This polls the server for any updates, but unlike Ajax, only listens for the text/event-stream mime):
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
alert(event.data);
};
The efficient part is that you can then update this with ActionController::Live::SSE in Rails. I don't have any experience with this, but it basically allows you to send updates via the text/event-stream mime type
WebSockets
Websockets basically open a perpetual connection with your server, allowing you to receive content above the normal HTTP scope
My experience does not extend to "native" websockets (we've successfully used Pusher, and are working on our own websock implementation); but I can say that it's basically a more in-depth version of SSE's
You'll have to use JS to authenticate the client-server connection, and once connected, the browser will listen for updates. I'm not sure about the mime-type for this, but reading up on ActionController::Live will give you some insight into how it works
Either one of these methods will do as you need (only send / receive updates as they are available)

Phusion passenger spawner rails app causing high cpu usage

I have Asterisk and Rails app running on the same server. All inbound calls via Asterisk triggers a "curl" to the rails app's controller to initiate a juggernaut publish, enabling real-time push of inbound calls to the individual logged in user (Pop-up dialog showing caller profile details).
The problem is, the Passenger Spawner of the rails app is running at almost 100% CPU usage when ever calls starts coming in. Each inbound phone call will run:
/usr/bin/curl http://parlo.local/asterisk/inbound_call?exten=8405&src_num=921187888&recordingfilename=q70001-20
In asterisk controller:
def inbound_call
if params[:src_num].length > 6
extension = AsteriskUserextension.find_by_extension(params[:exten])
if extension.present? && extension.user.present?
#user = extension.user
customer = Customer.first_match(params[:src_num]).first
customer_name = customer.present? ? customer.full_name : "Unknown Caller"
queue = AsteriskQueue.find_by_name(params[:queue])
#result = Asterisk::Action.response_factory("asterisk_inbound","#{queue.try(:title)}","OK",customer.try(:id))
publish
end
end
render :nothing => true, :status => :created
end
I believe the high inbound call rate is causing the high CPU usage. What is the best way to remedy this situation? Will pushing all the work to RESQUE help?
Thanks for any guidance!
You need use FastCGI technology.
Also you need in asterisk use CURL function instead of System application.
Every call to System create shell and fork new proccess.
Also it can be nice idea check asterisk events via AMI instead of dooign CURL.

Resources