Autodesk DM API: Is Retry appropriate here? - autodesk-forge

I've got an application that's been working for a long time.
Recently we created a new app/keys for it, and it's behaving strangely.
(I did figure out the scope requirements had been put in place. I am requesting bucket:create bucket:read data:read data:write).
When I upload a file to a bucket, I've traditionally called done the call to get the object details afterwards, to verify that it's successfully uploaded.
With the new key, I am intermittently getting this error:
GetObjectDetails: InternalServerError {"fault":{"faultstring":"Execution of ServiceCallout servicecallout-auth-acm-request failed. Reason: timeout occurred servicecallout-auth-acm-request","detail":{"errorcode":"steps.servicecallout.ExecutionFailed"}}}
Is this something I should be re-trying with a sleep in between? or is it indicative of something wrong with the upload?
(FYI - putting in a retry seems to have have resolved this for me, but I still don't know if that's the right answer - and if this issue might happen on other calls).

It could be that the service requires a slight delay between a put object and a get, so I would suggest either use a timer or a retry as you mentioned. However a successful response from the upload should be enough to ensure your object has been placed to the bucket without the need to double check.

Related

How to handle "Unexpected EOF at target" error from API calls?

I'm creating a Forge application which needs to get version information from a BIM 360 hub. Sometimes it works, but sometimes (usually after the code has already been run once this session) I get the following error:
Exception thrown: 'Autodesk.Forge.Client.ApiException' in mscorlib.dll
Additional information: Error calling GetItem: {
"fault":{
"faultstring":"Unexpected EOF at target",
"detail": {
"errorcode":"messaging.adaptors.http.flow.UnexpectedEOFAtTarget"
}
}
}
The above error will be thrown from a call to an api, such as one of these:
dynamic item = await itemApi.GetItemAsync(projectId, itemId);
dynamic folder = await folderApi.GetFolderAsync(projectId, folderId);
var folders = await projectApi.GetProjectTopFoldersAsync(hubId, projectId);
Where the apis are initialized as follows:
ItemsApi itemApi = new ItemsApi();
itemApi.Configuration.AccessToken = Credentials.TokenInternal;
The Ids (such as 'projectId', 'itemId', etc.) don't seem to be any different when this error is thrown and when it isn't, so I'm not sure what is causing the error.
I based my application on the .Net version of this tutorial: http://learnforge.autodesk.io/#/datamanagement/hubs/net
But I adapted it so I can retrieve multiple nodes asynchronously (for example, all of the nodes a user has access to) without changing the jstree. I did this to allow extracting information in the background without disrupting the user's workflow. The main change I made was to add another Route on the server side that calls "GetTreeNodeAsync" (from the tutorial) asynchronously on the root of the tree and then calls it on each of the returned children, then each of their children, and so on. The function waits until all of the nodes are processed using Task.WhenAll, then returns data from each of the nodes to the client;
This means that there could be many api calls running asynchronously, and there might be duplicate api calls if a node was already opened in the jstree and then it's information is requested for the background extraction, or if the background extraction happens more than once. This seems to be when the error is most likely to happen.
I was wondering if anyone else has encountered this error, and if you know what I can do to avoid it, or how to recover when it is caught. Currently, after this error occurs, it seems that every other api call will throw this error as well, and the only way I've found to fix it is to rerun the code (I use Visual Studio so I just rerun the server and client, and my browser launches automatically)
Those are sporadic errors from our apigee router due to latency issues in the authorization process that we are currently looking into internally.
When they occur please cease all your upcoming requests, wait for a few minutes and retry again. Take a look at stuff like this or this to help you out.
And our existing reports calling out similar errors seem to point to concurrency as one of the factors leading up to the issue so you might also want to limit your concurrent requests and see if that mitigate the issue.

Model derivative translate job giving status code 409 (CONFLICT)

How to fix status code 409 for translate job.
There are two types of problems I am facing.
1. Sometimes API returns error status code 409(conflict)
2. Sometimes it continuously gives in progress status and never completes or fails even.
Once any of the above error occurs, any subsequent job requests starts failing with error code 409.
We are trying node js API for translating job using following code.
let translateResult = derivativesAPI.translate(job, { 'xAdsForce': true }, forgeSvc.requestOAuth2TwoLeggedOBJ(), accessToken);
First try to delete manifest for the stuck/pending request file,
If that doesn't works , last option is to delete the bucket with pending/stuck translation request and then try again.
As per documentation, the 409 means:
The request conflicts with a previous request that is still in progress
As you mentioned a previous request failed, but is pending on our system and causes this conflict. Is that happening consistently with a file? Or random? When it fails (or hangs), what's the manifest? Finally, can you share a problematic URN?
EDIT: the file is working now and we'll keep investigating this.

SharedObject: can receive event from other clients but never fires event after saving data

I'm using a SharedObject to create a simple chat app. The SharedObject was created fine and my app could receive the sync event when other clients updates the data on the SO. However, the problem comes when my app tries to saves the data on the SO to signal other clients. I've verified that the data was changed using the following code:
trace("before:"+so.data.chatMessage);
so.data.chatMessage = msg.text;
trace("after:"+so.data.chatMessage);
It said "before:abc" and "after:def". Unfortunately no clients received the sync event after the data on the SO changed including the client that made the data change itself. So this means this client can receive other client's message but itself message never gets out.
Anybody has seen such issue before? Thanks,
Jack
You have to call flush():
If you don't use this method, Flash Player writes the shared object to a file when the shared object session ends — that is, when the SWF file is closed, when the shared object is garbage-collected because it no longer has any references to it, or when you call SharedObject.clear() or SharedObject.close().
or
use setProperty() to change the property:
Updates the value of a property in a shared object and indicates to the server that the value of the property has changed.
As you only change a property of the data object, there's no notification going on that this value has changed.
Calling so.flush() resulted in "Error: Error #2130: Unable to flush SharedObject." It did not print an internal error, though. So it seems the problem was the flush couldn't be successful... Any idea how could happen?
Take a look at this other question:
Error #2130 Unable to flush sharedObject

Service Worker not prompting to be registered - net::ERR_FILE_EXISTS

I browsed through the other threads - there was no concrete answer.
I implemented a service worker for notifcations
http://docs.pushwoosh.com/docs/chrome-web-push
I checked everything - all scripts are in root, the keys are well implemented. However, I do not get prompted to allow notifs.
Console output reads:
GET https://mydomain/service-worker.js net::ERR_FILE_EXISTS
Note: I do have the correct URL (just changed it here).
What causes the service worker error? How do I fix this?
It isn't anything to worry about. See the internal bug report: https://code.google.com/p/chromium/issues/detail?id=541797 the TL'DR is that when Chrome tries to fetch a new SW if there is no change and thus nothing to install it throws this error message to indicate that state. There is nothing that you need to do.

How do BundleActivator, ManagedService, and my application interact on start/stop?

I had a non-OSGi application. To convert it to OSGi, I first bundled it up and gave it a simple BundleActivator. The activator's start() started up a thread of what used to be the main() of my app (and is now a Runnable), and remembered that thread. The activator's stop() interrupted that thread, and waited for it to end (via join()), then returned. This all seemed to be working fine.
As a next step in the OSGiification process, I am now trying to use OSGi configuration management instead of the Properties-based configuration that the application used to use. So I am adding in a ManagedService in addition to the Activator.
But it's no longer clear to me how I am supposed to start and stop my application; examples that I've seen are only serving to confuse me. Specifically, here:
http://felix.apache.org/site/apache-felix-config-admin.html
They no longer seem to do any real starting of the application in BundleActivator.start(). Instead, they just register a ManagedService to receive configuration. So I'm guessing maybe I start up the app's main thread when I receive configuration, in the ManagedService? They don't show it - the ManagedService's updated() just has vague comments saying to "apply configuration from config admin" when it is passed a non-null Dictionary.
So then I look here:
http://blog.osgi.org/2010/06/how-to-use-config-admin.html
In there, it seems like maybe they're doing what I guessed. They seem to have moved the actual app from BundleActivator to ManagedService, and are dealing with starting it when updated() receives non-null configuration, stopping it first if it's already started.
But now what about when the BundleActivator's stop() gets called?
Back on the first example page that I mentioned above, they unregister the ManagedService. On the second example page, they don't show what they do.
So I'm guessing maybe unregistering the ManagedService will cause null configuration to be sent to ManagedService.updated(), at which point I can interrupte the app thread, wait for it to end, and then return?
I suspect that I'm thoroughly incorrect, but I don't know what the "real" way to do this is. Thanks in advance for any help.
BundleActivator (BA) and ManagedService (MS) are callbacks to your bundle. BundleActivator is for the active state of your bundle. BA.start is when you bundle is being started and BA.stop is when it is being stopped. MS is called to provide your bundle a configuration, if there is one, or notify you there is no configuration.
So in BA.start, you register your MS service and return. When MS is called (on some other thread), you will either receive your configuration or be told there is no configuration and you can act accordingly (start app, etc.)
Your MS can also be called at anytime to advice of the modification or deletion of your configuration and you should act accordingly (i.e. adjust your app behavior).
When you are called at BA.stop, you need to stop your app. You can unregister the MS or let the framework do it for you as part of normal bundle stop processing.