All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.bingads.reporting.ReportingOperationTracker Maven / Gradle / Ivy

Go to download

The Bing Ads Java SDK is a library improving developer experience when working with the Bing Ads services by providing high-level access to features such as Bulk API, OAuth Authorization and SOAP API.

There is a newer version: 13.0.23.2
Show newest version
package com.microsoft.bingads.reporting;

import com.microsoft.bingads.AsyncCallback;
import com.microsoft.bingads.internal.OperationStatusRetry;
import com.microsoft.bingads.internal.ParentCallback;
import com.microsoft.bingads.ServiceClient;
import com.microsoft.bingads.internal.ResultFuture;
import com.microsoft.bingads.internal.functionalinterfaces.Consumer;
import com.microsoft.bingads.internal.functionalinterfaces.TriConsumer;
import com.microsoft.bingads.internal.utilities.ThreadPool;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
 * Track the status of reporting operation.
 */
public class ReportingOperationTracker{
	
    private static final int INITIAL_STATUS_CHECK_INTERVAL_IN_MS = 1000;
    private static final int NUMBER_OF_INITIAL_STATUS_CHECKS = 5;
    
    private int numberOfStatusChecks = 0;
    private ScheduledExecutorService executorService;
    private ReportingStatusProvider statusProvider;
    private boolean stopTracking;
    protected int lastProgressReported;
    private ReportingOperationStatus currentStatus;
    private final int statusCheckIntervalInMs;

    private ResultFuture trackResultFuture;

    private ServiceClient serviceClient;
    
    private OperationStatusRetry operationStatusRetry;
    private int numberOfStatusRetry = 3;

    private final Runnable pollExecutorTask = new Runnable() {
        @Override
        public void run() {
            pollOperationStatus();
        }
    };

    public ReportingOperationTracker(
    		ReportingStatusProvider statusProvider,
            ServiceClient serviceClient,
            int statusCheckIntervalInMs) {

        this.statusCheckIntervalInMs = statusCheckIntervalInMs;
        this.statusProvider = statusProvider;
        this.serviceClient = serviceClient;
        this.operationStatusRetry = new OperationStatusRetry();
    }

    AtomicBoolean statusUpdateInProgress = new AtomicBoolean(false);

    public void pollOperationStatus() {
        try {
            if (!statusUpdateInProgress.compareAndSet(false, true)) {
                return;
            }

            if (trackingWasStopped()) {
                return;
            }

            if (cancelPollingIfRequestedByUser()) {
                return;
            }

            refreshStatus(new AsyncCallback() {
                @Override
                public void onCompleted(Future result) {
                    try {
                        result.get();

                        numberOfStatusChecks++;


                        completeTaskIfOperationIsComplete();
                    } catch (InterruptedException ex) {
                        stopTracking();

                        propagateExceptionToCallingThread(new CouldNotGetReportingDownloadStatusException(ex));
                    } catch (ExecutionException ex) {
                        stopTracking();
                        
                        propagateExceptionToCallingThread(new CouldNotGetReportingDownloadStatusException(ex));
                    } finally {
                        statusUpdateInProgress.set(false);

                        if (!stopTracking) {
                            int interval = INITIAL_STATUS_CHECK_INTERVAL_IN_MS;

                            if (numberOfStatusChecks >= NUMBER_OF_INITIAL_STATUS_CHECKS) {
                                interval = statusCheckIntervalInMs;
                            }

                            executorService.schedule(pollExecutorTask, interval, TimeUnit.MILLISECONDS);
                        }
                    }
                }
            });
        } catch (Throwable ex) {
            stopTracking();

            propagateExceptionToCallingThread(ex);
        }
    }

    private boolean cancelPollingIfRequestedByUser() {
        if (trackResultFuture.isCancelled()) {
            stopTracking();

            return true;
        }
        return false;
    }

    private void propagateExceptionToCallingThread(Throwable ex) {
        trackResultFuture.setException(ex);
    }

    private void completeTaskIfOperationIsComplete() {
        if (operationIsComplete()) {
            stopTracking();
            completeTaskWithResult();
        }
    }

    private void completeTaskWithResult() {
        trackResultFuture.setResult(currentStatus);
    }

    private boolean operationIsComplete() {
        return statusProvider.isFinalStatus(currentStatus);
    }

    private void refreshStatus(AsyncCallback callback) {
        final ResultFuture resultFuture = new ResultFuture(callback);
        
        operationStatusRetry.executeWithRetry(
        	new TriConsumer, AsyncCallback>() {
                @Override
                public void accept(ReportingStatusProvider statusProvider, ServiceClient serviceClient, 
                		AsyncCallback callback) {
                    statusProvider.getCurrentStatus(serviceClient, callback);
                }
            },
        	statusProvider,
        	serviceClient,
    		new Consumer() {
    			@Override
    			public void accept(ReportingOperationStatus status) {
    				currentStatus = status;

    				resultFuture.setResult(currentStatus);
    			}
    		},
    		new Consumer() {
    			@Override
    			public void accept(Exception exception) {
    				resultFuture.setException(exception);
    			}
    		},
    		numberOfStatusRetry
    	);
    }

    private boolean trackingWasStopped() {
        return this.stopTracking;
    }

    private void stopTracking() {
        this.stopTracking = true;

        this.executorService.shutdown();
    }
    
    public Future trackResultFileAsync(AsyncCallback callback) {
        this.trackResultFuture = new ResultFuture(callback);

        this.startTracking();

        return trackResultFuture;
    }

    private void startTracking() {
        executorService = Executors.newSingleThreadScheduledExecutor();
        
        executorService.schedule(pollExecutorTask, INITIAL_STATUS_CHECK_INTERVAL_IN_MS, TimeUnit.MILLISECONDS);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy