Confusing asynchronous operations for client.db.get(..)

We created a custom app that need to store and retrieve external IDs of a third party. We use then this IDs on external event to link with Ticket.

We have an issue with one of data storage call.
It breaks without error message.

The same code works well in local using sdk cli.

Mainly it’s a function that will test if the data storage exist, if not (error) it will call a function to create it.
If it exist it will update the value to add the new ID in the list.

Local:
Local 1 : data storage is initiated and we can see steps 1,2,3 in logs
Local 1

Local 2 : we adda another value and we can see stopes 1,4,5,6 in logs
Local 2

Production: the code stop at app.js:9 step 1 without any error from app.js.

You can see in source code file that then the action is to retrieve the data storage named “tickets_docusign_all” and
if success => log step 4
if error => log step 2

But console stop at step 1 app.js:9.

Is there an issue in our code ? But this is working correctly in local and was working in prod few weeks ago.

Thanks,

1 Like

Hi @JulienN,
Welcome to the Developer Community :tada:

Hope you are safe and sound.

Basing on the screenshot, the caller of the updateEnvelops function is returning post line 9 since the function is not having any callback. Can you please try adding callback as function parameter and call at the end of the function?

2 Likes

Hi @ManiDeepak_Vandrangi,

Thanks for your reply. Please could you give me an example of what you mean ?
Not sure to understand your advise.

Line 9 works , then the issue come on line 10 with data storage function.

Function updateEnvelops doesn’t need to return anything it’s just used to store data in data storage.

This function is called inside another one as shown below:

And the client.db.get() of the line 158 is working well…

Thanks,
Julien

1 Like
   function updateEnv(envelopeId, display_id, id, callback) {
        client.db.get( ).then( function(data) { callback() 
  }

pass callback and let it get called in client.db.get callback.

2 Likes

Thanks for your reply. Please could you give me an example of what you mean ?
Please could you give me the content of callback and i can call it ?

Thanks,
Hedi

1 Like

@ManiDeepak_Vandrangi thanks for your precision.
@hchoura tried adding a callback in the call please see below screens.
He define callback function but we got a log that function doesn’t exist

to be sure to understand how the script was proceed.

line 12 it started the function updateEnvelopeDocuSignAll with callback function in
it processed callback function with the log “callback”

Then it processed line 13 the log to display (1) - begin …
Then it fetch an error that it can’t access callback function but it processed it earlier …

I don’t understand how it works

1 Like

I would like to try providing a solution and make an attempt to solve your query. Since I don’t know the broader code, I will move forward with the details you’ve shared.

Problem as I understand

  1. The execution context of saveEnvelopeToTicket(..) has client.data.get() and client.db.get(..) statements.
  2. client.db.get(..)is a Promise.
  3. If client.db.get(..) either resolves or rejects (in other words, if the key exists or doesn’t exist in the db), updateEnvelopsDocusignAll(..) is invoked.
  4. In the execution context of updateEnvelopsDocusignAll(..) only [1] is logged to the console.
  5. The developer expects within updateEnvelopsDocusignAll(..) function, client.db.get(..) to be invoked. An upon resolving, either success operation or the failure operation should be executed.

So what happens to other steps? [2], [4], [5], [6]

My assumption is that, when the JS thread is in saveEnvelopeToTicket(..) execution context,

client.db.get('ticket_docusign:'+id) is a promise. When JS thread of execution invokes a promise, two things happen

  1. While the promise is resolving, the JS thread executes remaining JS statements in saveEnvelopeToTicket(..) 's execution context. The `success function on promise resolve is queued by JS (in a microtask queue).
  2. However, there are no further statements after client.db.get('ticket_docusign:'+id)
  3. The success function starts being executed by JS thread. Eventually updateEnvelopsDocusignAll(..) is invoked.
  4. JS looks in outer scope for updateEnvelopsDocusignAll(..) function and finds it. Its execution precisely has only two JS statements.
function updateEnvelopsDocusignAll(..) {
    console.log('[1] - add an envelope id in repository')
    client.db.get("tickets_docusign_all").then(function success(resolvedData) {
        // [4] - display current envelope list
        //  [5] - add envelope in list
    }, function fail(error) {
        // [2] - initiate storage
    })
}
  1. An console.log() to log [1]
  2. client.db.get("tickets_docusign_all") JS statement. Again it’s a promise. So JS thread of exectuation will continue to run existing code in updateEnvelopsDocusignAll(..) execution context. Meanwhile success function of client.db.get(..) will be queued. JS thread of execution returns undefined
  3. So only #5 statement executes and logs [1] to the console. You will have to tell the JS thread of execution to wait for client.db.get() either resolves or rejects in order to invoke success or fail functions respectively.

So,

function updateEnvelopsDocusignAll(..) {
    console.log('[1] - add an envelope id in repository')
    return new Promise((resolve, reject) => {
        client.db.get("tickets_docusign_all").then(function success(resolvedData) {
            // [4] - display current envelope list
            //  [5] - add envelope in list
           resolve('display and add envelope complete')
        }, function fail(error) {
            // [2] - initiate storage
          reject('initate storate done')
        })
    });
}
  1. This way in saveEnvelopeTicket(..), JS thread of execution when executes the queued success/fail function of client.db.get('ticket_docusing:'+id), it knows updateEnvelopsDocusignAll(..) is a promise and waits to be resolved.
function saveEnvelopeToTicket(..) {

    client.data.get("ticket").then(function(data) {
        clinet.db.get("ticket_docusing" + id).then(function(data) {
            ......
            updateEnvelopsDocusingAll(..).then(function success(data) {
                console.log(data); // display and add envelope complete

            }, function fail(err) {
                console.log(err); // initiate complete
            })
        }, function(err) {
            ..
        })
    }, function(error) {
        ..
    })

}

Let me know if that helped you make some progress. If yes, we will discuss, the following…

:warning: I am still struggling to understand how did this work locally in the first place and not in production. This might require me to have more context about the codebase. But we will visit this once you see some success with above suggestions.

5 Likes

@Saif Thank you so much for this step by step reply !

Unfortunately @hchoura updated the code following your advise and we failed at same step :frowning_face:

Please see below code changes:
Console 0611

source 0611 - 2

it seems still that code from line 10 to 22 doesn’t work …

1 Like

@JulienN - Can you confirm if the same worked on local simulation?

1 Like

@Saif We was not able to test the full app in local as there are some parameters and Fresh domains to be used.

@hchoura will try to create another function without external calls that need parameters, still investing.

2 Likes

@JulienN I will send a private message on this forum. So that we can investigate this issue by getting into specific details of it.

1 Like

@Saif What is strange is that I just uninstall and install again same app today.

I send a new envelope and data storage worked as expected on initiated data storage and update data storage.
see screens below

Please confirm that if our data storage value was >8KB we should have an error right and same regarding rate limit ?

1406 - log 1 1406 - log 2 1406- code 1

2 Likes

@Saif we had a call with someone from Fresh to review the issue.
The assumption was based on the data storage that could exceed 8KB but this still doesn’t explain why we can’t get in data or error function.

We changed our approach to use a unique key of 24 caracters and this is still not working.
Last log come from line 14.

At this stage we don’t know how to fix this and still don’t get why we can’t get in this success

Thanks,
Julien

1 Like

Hi @JulienN,

I read the above statement as problem is solved yet finding the cause of problem occurred in the first place. So I shifted focus on limits of Data Storage might as well be an cause.

but now I understand your problem persists.

I will reply to the on the private message that we were discussing. Let’s see if we can find a sample code or the either get on a call to solve this further using office hours.

2 Likes

@Saif we did another try with another function without data storage and we suspect the issue to be in the number of levels of function calls.

All failed seems at sub level 6

  1. click on button
  2. ShowConfirm
    2.1) SendEnvelope
    2.1.1) API DocuSign
    2.1.1.1) SaveEnvelopeToTicket
    2.1.1.1.1) client.data.get()
    2.1.1.1.1.1) updateEnvelopeTicket()
    2.1.1.1.1.2) UpdateEnvelopeDocuSign24
    2.1.1.1.1.2.1) StoreDocusignEnvelopeList
    2.1.1.1.1.2.2) SetDocuSIgnEnvelopeList
    2.1.1.2) ShowNotification



2 Likes

For the followers of this thread…

Here’s our best understanding.

  1. We had two JS functions invoked one by one in the same execution context – ABC(..) and XYZ(..)
  2. Both ABC(..) and XYZ(..) had methods when invoked will return promises.
  3. ABC(..) has client.db.get(..) which can be either fulfilled F1 or rejectedR1.
  4. XYZ(..) returns a promise to either fulfill F2 or rejectedR2.
  5. Javascript queues F1, F2 in a microtask queue. Both callbacks F1 and F2 will be invoked only when they are fulfilled. If JS encounters R1 during execution, JS will realize promise is rejected, and the thread of execution will move to the nearest .catch(..).
  6. In the current situation, app has expected ABC(..) -> XYZ(..) -> R1 -> F2 to happen. But JS as it should, ABC(..) -> XYZ(..) -> R1 -> .catch(..) and exits. The catch wasn’t defined so JS silently exits.
  7. We solved this problem forcing ABC(..) -> XYZ(..) -> F1 -> F2 -> if err -> .catch(..) to happen.

Here,
ABC(..) is updateEnvelopTicket(..)
XYZ(..) is updateEnvelopsDocusignAll(..)

Here is the sample we shared with the developer to do #7,

This topic will automatically close in 3 days.
For any new questions we request to either create a new topic
If you are this topic creator – we already have private thread where you can ask further questions.

2 Likes

This topic was automatically closed after 44 hours. New replies are no longer allowed.