Operation API loading issue

What product/components do you use and which version/fix level?

Cumulocity 1010.0.12

Are you using a free trial or a product with a customer license?

Customer License

What are trying to achieve? Please describe in detail.

We have build a widget, Where we are calling GET device control operation API (https://test.cumulocity.com/devicecontrol/operations/{operation ID}) and the API is in pending status on server but in my local it runs after multiple try and give me successful status.
There is two part first I post an operation API then that API successfully gives me operation ID but when I try to run GET API using the operation ID from post API, I got pending status in my browser network and in my widget even though the operation is successful in device management control section.
I believe the server is to fast and it didn’t give much time to GET API to completes.
I’m wondering what could be the possible reason and any help much appreciated.

API -
async getData(id) {
const response = await this.fetchClient.fetch(’/devicecontrol/operations/’ + id, this.options).then(handleErrors).catch(error => this.toasterService.error(${error}\n, “”, { positionClass: ‘toast-top-center’, timeOut: 300000000 })); // Fetch API Response
return response.json();
}

Do you get any error messages? Please provide a full error message screenshot and log file.

It’s pending in my browser!

But the same operation ID is successful in postman or device management.

Hi Saif,

as a general remark, if you communicate with Cumulocity’s API you can use the @c8y/client instead of the FetchClient. For the Operation API it is the OperationService.

For your issue, I think you shouldn’t simply poll the operation and its status using a GET request as it will result in multiple requests to check whether the status of the operation has been updated to successful. I suggest to use the Realtime API and subscribe for updates for your operations.

Realtime service needs to be injected into your service/component and then you can subscribe to different channels:

// realtime event
const subscription = realtime.subscribe('/operations/<<id>>', (data) => {
  console.log(data); // logs all operations CRUD changes
});
realtime.unsubscribe(subscription);

Basically you would receive notifications for the operation every time it has been updated. This includes also changes to its status.

Best regards
Christian

Hey @Christian_Guether1 ,

Thanks for the quick response, I changed the FetchClient API to OperationService and the response is quite same. The issue is on server deployment the response I get from the operation API is pending but in reality the operation is successful, The server doesn’t give much time to load.

API -
async getData(id) {
const response = await this.operationservice.detail(id)
return response.data;
}

API response -

c8y_Command: {text: “{“Update”:“AcquisitionRates”}”}
creationTime: “2022-01-11T11:29:56.040Z”
description: “Execute shell command: UpdateStatus”
deviceId: “31635012”
id: “36887681”
self: “https://solenis.us.cumulocity.com/devicecontrol/operations/36887681
status: “PENDING”

Can you please give me more information on how I can use the Realtime API here and what I need to subscribe here?

Thanks.

Hi Saif,

a minimal example to subscribe for notifications on operations for a specific device:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { IOperation, Realtime } from '@c8y/client'

@Component({
  selector: 'hello',
  templateUrl: './hello.component.html'
})
export class HelloComponent implements OnInit, OnDestroy {
  private readonly DEVICE_ID = '701';

  private subscription: object;

  constructor(private realtime: Realtime) { }

  ngOnInit(): void {
    this.subscription = this.realtime.subscribe(`/operations/${this.DEVICE_ID}`, ((notification) => {
      const operation: IOperation = notification.data.data;
      console.log('operation update received: ', operation);
    }));
  }

  ngOnDestroy(): void {
    this.realtime.unsubscribe(this.subscription);
  }
}

The Realtime service is injected as a dependency. In the onInit method the component subscribes for notifications on operations using the Realtime service and the channel /operations/. In this case, the component subscribes for operations of a particular device: private readonly DEVICE_ID = '701'; via /operations/${this.DEVICE_ID}. Using this subscription, the component only receives notifications, which have been created/updated for this specific device. If you want to receive operations for all devices, you can set up a subscription and use the * as a wildcard: /operations/*.

By using this approach you will be informed about every operation status updates.

Best regards
Christian