1

I recently upgraded my metadata service from version 29.0 to 32.0 and I'm having some difficulties with the checkRetrieveStatus method (new method as of version 31.0 - see quote). The code included below throws exceptions from time to time; it is not consistent, so I'm here hoping you experts can help.

In API version 31.0 and later, the process of making a retrieve() call has been simplified. You no longer have to call checkStatus() after a retrieve() call to obtain the status of the retrieve operation. Instead, make calls to checkRetrieveStatus() only. If the retrieve operation is in progress, call checkRetrieveStatus() again until the retrieve operation is completed. The checkStatus() call is still supported in versions API version 30.0 or earlier, but is not available in API version 31.0 and later.

Please note this code worked in version 29.0 using the deprecated checkStatus method.

Here's a sample exception from Salesforce (thrown when I call checkRetrieveStatus):

INVALID_ID_FIELD: Deployment still in process: InProgress <-- enum varies; sometimes it's "Queued"

It's difficult to know if/when I've solved the problem because the behavior is inconsistent.

Has anyone experienced this issue? Any suggestions are greatly appreciated - I'm still fairly new to the Salesforce APIs.

Thanks, Tyler

    private static byte[] GetReportsZipArchiveContents(FileProperties[] serviceQueryResults)
    {
        Package package = new Package();
        package.apiAccessLevel = APIAccessLevel.Unrestricted;
        package.version = WebService.SalesforceApiVersion.ToString("0.0");

        PackageTypeMembers packageTypeMembers = new PackageTypeMembers();
        packageTypeMembers.members = new string[] { "*" };
        packageTypeMembers.name = "Report";

        package.types = new PackageTypeMembers[] { packageTypeMembers };

        using(SalesforceMetadataService webService = new SalesforceMetadataService())
        using(MetadataService metadataService = webService.GetMetadataService())
        {
            AsyncResult asyncResult = metadataService.retrieve(
                new RetrieveRequest {
                    apiVersion = WebService.SalesforceApiVersion,
                    packageNames = null,
                    singlePackage = true,
                    specificFiles = serviceQueryResults.Select(fileProperty => fileProperty.fileName).ToArray(),
                    unpackaged = package
                }
            );

            DateTime pollingTimeoutCheckValve = DateTime.Now.AddSeconds(DefaultPollingTimeoutInSeconds);

            RetrieveResult result = metadataService.checkRetrieveStatus(asyncResult.id);

            while(!result.done)
            {
                if(DateTime.Now >= pollingTimeoutCheckValve)
                {
                    // Log a message and exit method.
                }

                Thread.Sleep(250);

                result = metadataService.checkRetrieveStatus(asyncResult.id);
            }

            if(result.done && !result.success)
            {
                string retrieveProblems = result.messages
                    .Select(message => string.Format("{0} ({1})", message.problem, message.fileName))
                    .Concatenate(", ");

                string exceptionMessage = string.Format(
                    "An error occurred while attempting to retrieve Reports from Salesforce: {0}.",
                        retrieveProblems
                    );

                throw new SalesforceQueryException(exceptionMessage);
            }

            webService.RefreshLoginExpiration();

            return result.zipFile;
        }
    }
0

One thing to try would be checking the AsyncResult before proceeding to poll the retrieve status.

If the AsyncResult.done property is true then there is no need to check the retrieve status. You could also check if the AsyncResult.state is Error before proceeding to poll for the retrieve result. If it is Error, check the AsyncResult.statusCode property.

Do note however that the documentation says (my emphasis):

In API version 31.0, the process of retrieving metadata has been simplified and retrieval properties have been moved to RetrieveResult. Also, the asynchronous create(), update(), and delete() calls have been removed. Therefore, only the id field in AsyncResult is used. The id field is the ID of a deployment or retrieval.

So you may still need to check the RetrieveResult.

  • Great input, Daniel. I'll apply your suggestions. Thanks! – confused.developer Nov 17 '14 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.