Race-condition with web workers when setting onmessage handler? - html

Please consider the following code and the explanation from this Mozilla tutorial "Using web workers":
var myWorker = new Worker('my_worker.js');
myWorker.onmessage = function(event) {
print("Called back by the worker!\n");
};
Line 1 in this example creates and
starts running the worker thread.
Line 2 sets the onmessage handler for
the worker to a function that is
called when the worker calls its own
postMessage() function.
The thread is started in the moment the Worker constructor is called. I wonder if there might be a race-condition on setting the onmessage handler. For example if the web worker posts a message before onmessage is set.
Does someone know more about this?
Update:
Andrey pointed out that the web worker should start its work, when it receives a message, like in the Fibonacci example in the Mozilla tutorial. But doesn't that create a new race-condition on setting the onmessage handler in the web worker?
For example:
The main script:
var myWorker = new Worker('worker.js');
myWorker.onmessage = function(evt) {..};
myWorker.postMessage('start');
The web worker script ('worker.js')
var result = [];
onmessage = function(evt) {..};
And then consider the following execution path:
main thread web worker
var worker = new Worker("worker.js");
var result = [];
myWorker.onmessage = ..
myWorker.postMessage('start');
onmessage = ..
The "var result = []" line can be left out, it will still be the same effect.
And this is a valid execution path, I tried it out by setting a timeout in the web worker! At the moment I can not see, how to use web workers without running into race-conditions?!

The answer is that both the main script and the web worker have a MessagePort queue which collects the messages before the initial worker script returns.
For details, see this thread on the WHATWG help mailing list:
http://lists.whatwg.org/pipermail/help-whatwg.org/2010-August/000606.html

Related

Autodesk forge activity "Gateway Timeout" activating master view

Activating master view as in MasterView I created:
var advOutputPayload = new JobSvf2OutputPayloadAdvanced();
advOutputPayload.GenerateMasterViews = true;
// prepare the payload
List<JobPayloadItem> outputs = new List<JobPayloadItem>()
{
new JobPayloadItem(
JobPayloadItem.TypeEnum.Svf,
new List<JobPayloadItem.ViewsEnum>()
{
JobPayloadItem.ViewsEnum._2d,
JobPayloadItem.ViewsEnum._3d
},
advOutputPayload
)
};
JobPayload obJob = new JobPayload(new JobPayloadInput(b64(info.revitFileUrn)), new JobPayloadOutput(outputs));
then I call with 'x-ads-force: true' using the SDK:
dynamic jobPosted = await derivative.TranslateAsync(jobPayload, force);
Where force is set to true.
And sometimes it works perfectly fine but sometimes I get this two errors:
Case 1
Error calling Translate: {"fault":{"faultstring":"Gateway Timeout","detail":{"errorcode":"messaging.adaptors.http.flow.GatewayTimeout"}}}
Case 2 (when I try to rerun.):
{"Result":"Conflict","Diagnostic":"The request is rejected as it conflicts with a previous request that is in-progress."...
What I am doing wrong or what I should do?
The network jitter might cause the 504 Gateway Timeout error since it could not reproduce on your side now. If it occurs again, feel free to report to us via forge[DOT]help[AT]autodesk[DOT]com.
Regarding the 409 Conflict error, it means that Forge service has accepted your previous request translation job and it's processing the job, but you request another translation job with x-ads-force=true, then it returns 409 Conflict. if you retry without x-ads-force=true, then it will return 201 Created, according to our engineering team.
Hope it's clear enough to you.

getUser does not work in 4.0.4 master webchat client

I downloaded today the last release (4.0.4, from yesterday) of the webchat client from github and deployed in in my website.
I have detected that Smooch.getUser() returns 'undefined' when a new user is detected until this new user send his first message, but it doesn't happen on returning users.
<script>
Smooch.on('ready', function(){
console.log('the init has completed!');
});
var skPromise = Smooch.init({appId: 'myAppId'});
skPromise.then(
function()
{
var u = Smooch.getUser();
console.log(u._id);
});
);
</script>
smooch_local.html:26 Uncaught (in promise) TypeError: Cannot read property '_id' of undefined
at smooch_local.html:26
at anonymous
But, if i send any message after the promise has resolved, and later I try to recover the userId, the variable gets defined. It didn't happen in this way in previous 3.x.x releases of the Web Messenger chat.
This code returns a valid userId:
<script>
Smooch.on('ready', function(){
console.log('the init has completed!');
});
var skPromise = Smooch.init({appId: 'myAppId'});
skPromise.then(
function()
{
Smooch.sendMessage({type: 'text', text: 'x'}).then(
function(){
var u = Smooch.getUser();
console.log(u._id);
});
}
);
</script>
This is the console ouptut:
12:21:20.165 the init has completed!
12:21:22.947 smooch_local.html:28 1102fdee2b7d3c2abb639cbe
Does anyone knows if it's a bug or a new feature from v4.x releases?
Thanks
This is expected behaviour for Web Messenger 4.x - users are no longer automatically created at init time. Instead, user creation is deferred until after they send a message. This was mentioned in the release notes for v4.0.0
Web Messenger now uses a new optimized initialization sequence. This new sequence alters the timing of key events such as creating a new user or establishing a websocket connection.
Alternatively, you can pre-create a user with a userId before the Web Messenger is initialized, and use the login method to initialize as that user, but this may or may not be appropriate depending on your use case.

How to send WebSocket events from blocking operation? (Design advice needed)

I use Mojolicious WebSocket to establish server-client messaging protocol.
There is long-time operation on server and I want update its progress on client-side.
In several points on server-side code I call $web_socket->send(...) and process it on client-side ws.onmessage = function (event) {...};
Everything work fine, but not in realtime: all messages has received by client at one big bulk list and only after whole server-side script has finished.
Server-side logic:
some_computation1();
$web_socket->send('computation1 end');
...
some_computation15();
$web_socket->send('computation15 end');
...
some_computation100();
$web_socket->send('computation100 end. All ok!');
Client-side:
ws = new WebSocket(url);
ws.onmessage = function (event) {
$('#log_view').append('<p>' + event.data + '</p>');
};
ws.onopen = function (event) {
...
};
ws.onclose = function (event) {
...
};
There is two example how to make it using one of two modules:
Mojo::IOLoop::ReadWriteFork
Mojo::IOLoop::ForkCall
To run it execute command:
perl perl_ws_long_blocking_operation.pl daemon
Upd.
If you have many long blocking operations you should use Mojo::IOLoop::Delay:
Example of many long blocking operation
To run it execute command:
morbo perl_ws_many_long_blocking_operations.pl
I found this works for me: Mojo::IOLoop->one_tick;
some_computation1();
$web_socket->send('computation1 end');
Mojo::IOLoop->one_tick;
UPD: or may be it will be better to separate long operation in background thread ('fork' or 'delay').

Chrome Push Notification: This site has been updated in the background

While implementing the chrome push notification, we were fetching the latest change from our server. While doing so, the service-worker is showing an extra notification with the message
This site has been updated in the background
Already tried with the suggestion posted here
https://disqus.com/home/discussion/html5rocks/push_notifications_on_the_open_web/
But could not find anything useful till now. Is there any suggestion ?
Short Answer: You should use event.waitUntil and pass a promise to it, which returns showNotification eventually. (if you have any other nested promises, you should also return them.)
I was expriencing the same issue but after a long research I got to know that this is because delay happen between PUSH event and self.registration.showNotification(). I only missed return keyword before self.registration.showNotification()`
So you need to implement following code structure to get notification:
var APILINK = "https://xxxx.com";
self.addEventListener('push', function(event) {
event.waitUntil(
fetch(APILINK).then(function(response) {
return response.json().then(function(data) {
console.log(data);
var title = data.title;
var body = data.message;
var icon = data.image;
var tag = 'temp-tag';
var urlOpen = data.URL;
return self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
});
})
);
});
Minimal senario:
self.addEventListener('push', event => {
const data = event.data.json();
event.waitUntil(
// in here we pass showNotification, but if you pass a promise, like fetch,
// then you should return showNotification inside of it. like above example.
self.registration.showNotification(data.title, {
body: data.content
})
);
});
I've run into this issue in the past. In my experience the cause is generally one of three issues:
You're not showing a notification in response to the push
message. Every time you receive a push message on the device, when
you finish handling the event a notification must be left visible on
the device. This is due to subscribing with the userVisibleOnly:
true option (although note this is not optional, and not setting it
will cause the subscription to fail.
You're not calling event.waitUntil() in response to handling the event. A promise should be passed into this function to indicate to the browser that it should wait for the promise to resolve before checking whether a notification is left showing.
For some reason you're resolving the promise passed to event.waitUntil before a notification has been shown. Note that self.registration.showNotification is a promise and async so you should be sure it has resolved before the promise passed to event.waitUntil resolves.
Generally as soon as you receive a push message from GCM (Google Cloud Messaging) you have to show a push notification in the browser. This is mentioned on the 3rd point in here:
https://developers.google.com/web/updates/2015/03/push-notificatons-on-the-open-web#what-are-the-limitations-of-push-messaging-in-chrome-42
So it might happen that somehow you are skipping the push notification though you got a push message from GCM and you are getting a push notification with some default message like "This site has been updated in the background".
This works, just copy/paste/modify. Replace the "return self.registration.showNotification()" with the below code. The first part is to handle the notification, the second part is to handle the notification's click. But don't thank me, unless you're thanking my hours of googling for answers.
Seriously though, all thanks go to Matt Gaunt over at developers.google.com
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = 'YOUR_ICON';
var tag = 'simple-push-demo-notification-tag';
var data = {
doge: {
wow: 'such amaze notification data'
}
};
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag,
data: data
})
);
});
self.addEventListener('notificationclick', function(event) {
var doge = event.notification.data.doge;
console.log(doge.wow);
});
I was trying to understand why Chrome has this requirement that the service worker must display a notification when a push notification is received. I believe the reason is that push notification service workers continue to run in the background even after a user closes the tabs for the website. So in order to prevent websites from secretly running code in the background, Chrome requires that they display some message.
What are the limitations of push messaging in Chrome?
...
You have to show a notification when you receive a push message.
...
and
Why not use Web Sockets or Server-Sent Events (EventSource)?
The advantage of using push messages is that even if your page is closed, your service worker will be woken up and be able to show a notification. Web Sockets and EventSource have their connection closed when the page or browser is closed.
If you need more things to happen at the time of receiving the push notification event, the showNotification() is returning a Promise. So you can use the classic chaining.
const itsGonnaBeLegendary = new Promise((resolve, reject) => {
self.registration.showNotification(title, options)
.then(() => {
console.log("other stuff to do");
resolve();
});
});
event.waitUntil(itsGonnaBeLegendary);
i was pushing notification twice, once in the FCM's onBackgroundMessage()
click_action: "http://localhost:3000/"
and once in self.addEventListener('notificationclick',...
event.waitUntil(clients.matchAll({
type: "window"
}).then...
so i commented click_action, ctrl+f5 to refresh browsers and now it works normal

NotificationHubNotFoundException Windows Phone 8

While I´ve been trying to make the basic notification hub tutorial work on my Windows Phone solution with the following code
var channel = HttpNotificationChannel.Find("MyPushChannel3");
if (channel == null)
{
channel = new HttpNotificationChannel("MyPushChannel3");
channel.Open();
channel.BindToShellToast();
}
channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(async (o, args) =>
{
var hub = new NotificationHub("http://messaging-ns.servicebus.windows.net/messagingt", "---MY CONECTION STRING---");
await hub.RegisterNativeAsync(args.ChannelUri.ToString());
});
I get a NotificationHubNotFoundException in the await line with the following message
HTTP request failed.
HTTP Details:
Status: 404
Reason: Not Found
Full content: 404No service is hosted at the specified address..TrackingId:2e4b1100-18de-4b24-bbec-68516ddc3b60_G4,TimeStamp:2/2/2014 1:30:23 AM
I tried a number of options for the first parameter of the NotificationHub constructor called "notificationHubPath" with no luck to get my app registered. Anyone has faced this error in the past. Unfortunately there are not enough documentation in how does this constructor works in MDSN.
Thanks
When creating the NotificationHub type object, try by passing just the hub name with the connection string, not the whole address:
var hub = new NotificationHub("messagingt", "---CONECTION STRING---");
I had the same issue, and after close/open VS2013, restart PC and change Wifi/3g connection it worked again like before... strange, i suppose that was a internet connection issue.
you can use fiddler to show more information, i forgot in my case...