com.arm.mbed.cloud.sdk.connect.subscription.NotificationHandlersStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mbed-cloud-sdk Show documentation
Show all versions of mbed-cloud-sdk Show documentation
The Pelion Cloud SDK (formerly known as Mbed Cloud SDK) provides a simplified interface to the Pelion Cloud APIs by exposing functionality using conventions and paradigms familiar to Java developers.
package com.arm.mbed.cloud.sdk.connect.subscription;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import com.arm.mbed.cloud.sdk.annotations.Internal;
import com.arm.mbed.cloud.sdk.annotations.Nullable;
import com.arm.mbed.cloud.sdk.annotations.Preamble;
import com.arm.mbed.cloud.sdk.common.AbstractApi;
import com.arm.mbed.cloud.sdk.common.Callback;
import com.arm.mbed.cloud.sdk.common.CloudCaller;
import com.arm.mbed.cloud.sdk.common.CloudCaller.CallFeedback;
import com.arm.mbed.cloud.sdk.common.CloudRequest.CloudCall;
import com.arm.mbed.cloud.sdk.common.ConnectionOptions;
import com.arm.mbed.cloud.sdk.common.GenericAdapter;
import com.arm.mbed.cloud.sdk.common.GenericAdapter.Mapper;
import com.arm.mbed.cloud.sdk.common.MbedCloudException;
import com.arm.mbed.cloud.sdk.common.SdkLogger;
import com.arm.mbed.cloud.sdk.common.TimePeriod;
import com.arm.mbed.cloud.sdk.connect.model.EndPoints;
import com.arm.mbed.cloud.sdk.connect.model.Resource;
import com.arm.mbed.cloud.sdk.internal.mds.model.NotificationMessage;
import com.arm.mbed.cloud.sdk.subscribe.CloudSubscriptionManager;
import com.arm.mbed.cloud.sdk.subscribe.NotificationCallback;
import com.arm.mbed.cloud.sdk.subscribe.NotificationMessageValue;
import com.arm.mbed.cloud.sdk.subscribe.SubscriptionType;
import com.arm.mbed.cloud.sdk.subscribe.adapters.AsynchronousResponseNotificationAdapter;
import com.arm.mbed.cloud.sdk.subscribe.adapters.DeviceStateNotificationAdapter;
import com.arm.mbed.cloud.sdk.subscribe.adapters.ResourceValueNotificationAdapter;
import com.arm.mbed.cloud.sdk.subscribe.model.AsynchronousResponseObserver;
import com.arm.mbed.cloud.sdk.subscribe.model.FirstValue;
import com.arm.mbed.cloud.sdk.subscribe.model.ResourceValueNotification;
import com.arm.mbed.cloud.sdk.subscribe.store.SubscriptionObserversStore;
import retrofit2.Call;
@Preamble(description = "Internal store for notification handlers")
@Internal
public class NotificationHandlersStore implements Closeable {
private static final int IDLE_TIME_BETWEEN_NOTIFICATION_PULL_CALLS = 50;
private static final TimePeriod REQUEST_TIMEOUT = new TimePeriod(50);
private final AbstractApi api;
private final ExecutorService pullThreads;
private Future> pullHandle;
private final EndPoints endpoint;
private final ExecutorService customSubscriptionHandlingExecutor;
private final SubscriptionObserversStore observerStore;
/**
* Notification store constructor.
*
* @param api
* API module
* @param pullingThread
* thread pool
* @param endpoint
* endpoint
* @param subscriptionHandlingExecutor
* subscription handling executor
*/
public NotificationHandlersStore(AbstractApi api, ExecutorService pullingThread,
ExecutorService subscriptionHandlingExecutor, EndPoints endpoint) {
super();
this.pullThreads = pullingThread;
this.endpoint = createNotificationPull(endpoint);
this.api = api;
pullHandle = null;
customSubscriptionHandlingExecutor = subscriptionHandlingExecutor;
observerStore = new SubscriptionObserversStore((customSubscriptionHandlingExecutor == null) ? Schedulers.computation()
: Schedulers.from(customSubscriptionHandlingExecutor),
new ResourceSubscriber(api, FirstValue.getDefault()),
new ResourceUnsubscriber(api, FirstValue.getDefault()));
}
private EndPoints createNotificationPull(EndPoints endpoint2) {
if (endpoint2 == null) {
return null;
}
final ConnectionOptions options = endpoint2.getConnectionOptions();
options.setRequestTimeout(REQUEST_TIMEOUT);
return new EndPoints(options);
}
public CloudSubscriptionManager getSubscriptionManager() {
return observerStore;
}
/**
* Starts notification pull.
*/
public void startNotificationPull() {
if (isPullingActive()) {
logInfo("Notification pull is already working.");
return;
}
final Runnable pollingSingleAction = createPollingSingleAction();
pullHandle = null;
if (pullThreads instanceof ScheduledExecutorService) {
pullHandle = ((ScheduledExecutorService) pullThreads).scheduleWithFixedDelay(pollingSingleAction, 0,
IDLE_TIME_BETWEEN_NOTIFICATION_PULL_CALLS,
TimeUnit.MILLISECONDS);
} else {
pullHandle = pullThreads.submit(new Runnable() {
@Override
public void run() {
while (true) {
pollingSingleAction.run();
try {
// Sleeping between calls
Thread.sleep(IDLE_TIME_BETWEEN_NOTIFICATION_PULL_CALLS);
} catch (InterruptedException exception) {
logPullError(exception);
}
}
}
});
}
}
/**
* Stops notification pull.
*/
public void stopNotificationPull() {
if (pullHandle != null && !(pullHandle.isDone() || pullHandle.isCancelled())) {
pullHandle.cancel(true);
}
pullHandle = null;
}
/**
* States whether pulling is currently on going.
*
* @return true if pulling is active. false otherwise.
*/
public boolean isPullingActive() {
return pullHandle != null;
}
/**
* Shuts down the store and the thread pool it uses.
*/
public void shutdown() {
logDebug("Shutting down polling thread");
if (pullThreads != null) {
pullThreads.shutdown();
}
logDebug("Clearing notification handler store");
try {
clearStores();
} catch (Exception exception) {
logError("Failed clearing notification handler store", exception);
}
logDebug("Shutting down notification threads");
if (customSubscriptionHandlingExecutor != null) {
customSubscriptionHandlingExecutor.shutdown();
}
// shutting down schedulers can have side effects
// logDebug("Shutting down notification schedulers");
// try {
// Schedulers.shutdown();
// } catch (Exception exception) {
// logError("Failed shutting down notification schedulers", exception);
// }
}
protected void logDebug(String message) {
final SdkLogger logger = api == null ? null : api.getLogger();
if (logger != null) {
logger.logDebug(message);
}
}
protected void logError(String message, Exception exception) {
final SdkLogger logger = api == null ? null : api.getLogger();
if (logger != null) {
logger.logError(message, exception);
}
}
protected void logInfo(String message) {
final SdkLogger logger = api == null ? null : api.getLogger();
if (logger != null) {
logger.logInfo(message);
}
}
/**
* Registers resource subscription callback.
*
* @param resource
* resource to register the callback for.
* @param onNotification
* callback to execute on notification.
* @param onFailure
* callback to execute on error.
*/
public void registerSubscriptionCallback(Resource resource, Callback