use of com.microsoft.azure.mobile.CancellationException in project mobile-center-sdk-android by Microsoft.
the class DefaultChannel method enqueue.
/**
* Actual implementation of enqueue logic. Will increase counters, triggers of batching logic.
*
* @param log the Log to be enqueued
* @param groupName the queue to use
*/
@Override
public synchronized void enqueue(@NonNull Log log, @NonNull final String groupName) {
/* Check group name is registered. */
final GroupState groupState = mGroupStates.get(groupName);
if (groupState == null) {
MobileCenterLog.error(LOG_TAG, "Invalid group name:" + groupName);
return;
}
/* Check if disabled with discarding logs. */
if (mDiscardLogs) {
MobileCenterLog.warn(LOG_TAG, "Channel is disabled, log are discarded.");
if (groupState.mListener != null) {
groupState.mListener.onBeforeSending(log);
groupState.mListener.onFailure(log, new CancellationException());
}
return;
}
/* Call listeners so that they can decorate the log. */
for (Listener listener : mListeners) listener.onEnqueuingLog(log, groupName);
/* Attach device properties to every log if its not already attached by a service. */
if (log.getDevice() == null) {
/* Generate device properties only once per process life time. */
if (mDevice == null) {
try {
mDevice = DeviceInfoHelper.getDeviceInfo(mContext);
} catch (DeviceInfoHelper.DeviceInfoException e) {
MobileCenterLog.error(LOG_TAG, "Device log cannot be generated", e);
return;
}
}
/* Attach device properties. */
log.setDevice(mDevice);
}
/* Set an absolute timestamp, we'll convert to relative just before sending. Don't do it if the service already set a timestamp.*/
if (log.getToffset() == 0L)
log.setToffset(System.currentTimeMillis());
/* Persist log. */
final int stateSnapshot = mCurrentState;
mPersistence.putLog(groupName, log, new DatabasePersistenceAsyncCallback() {
@Override
public void onSuccess(Object result) {
checkLogsAfterPut(groupState, stateSnapshot);
}
@Override
public void onFailure(Exception e) {
MobileCenterLog.error(LOG_TAG, "Error persisting log with exception: " + e.toString());
}
});
}
use of com.microsoft.azure.mobile.CancellationException in project mobile-center-sdk-android by Microsoft.
the class DefaultChannel method deleteLogsOnSuspended.
private synchronized void deleteLogsOnSuspended(GroupState groupState, int currentState, List<Log> logs) {
if (checkStateDidNotChange(groupState, currentState)) {
if (logs.size() > 0 && groupState.mListener != null) {
for (Log log : logs) {
groupState.mListener.onBeforeSending(log);
groupState.mListener.onFailure(log, new CancellationException());
}
}
if (logs.size() >= CLEAR_BATCH_SIZE && groupState.mListener != null) {
deleteLogsOnSuspended(groupState);
} else {
mPersistence.deleteLogs(groupState.mName);
}
}
}
use of com.microsoft.azure.mobile.CancellationException in project mobile-center-sdk-android by Microsoft.
the class DefaultChannelRaceConditionTest method disabledWhileHandlingIngestionFailure.
@Test
public void disabledWhileHandlingIngestionFailure() throws Exception {
/* Set up mocking. */
final Semaphore beforeCallSemaphore = new Semaphore(0);
final Semaphore afterCallSemaphore = new Semaphore(0);
Persistence mockPersistence = mock(Persistence.class);
when(mockPersistence.countLogs(anyString())).thenReturn(1);
when(mockPersistence.getLogs(anyString(), eq(1), anyListOf(Log.class))).then(getGetLogsAnswer(1));
when(mockPersistence.getLogs(anyString(), eq(CLEAR_BATCH_SIZE), anyListOf(Log.class))).then(getGetLogsAnswer(0));
DatabasePersistenceAsync mockPersistenceAsync = spy(new DatabasePersistenceAsync(mockPersistence));
whenNew(DatabasePersistenceAsync.class).withArguments(mockPersistence).thenReturn(mockPersistenceAsync);
IngestionHttp mockIngestion = mock(IngestionHttp.class);
final Exception mockException = new IOException();
when(mockIngestion.sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class))).then(new Answer<Object>() {
@Override
public Object answer(final InvocationOnMock invocation) throws Throwable {
new Thread() {
@Override
public void run() {
beforeCallSemaphore.acquireUninterruptibly();
((ServiceCallback) invocation.getArguments()[3]).onCallFailed(mockException);
afterCallSemaphore.release();
}
}.start();
return mock(ServiceCall.class);
}
});
/* Simulate enable module then disable. */
DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), mockPersistence, mockIngestion);
Channel.GroupListener listener = mock(Channel.GroupListener.class);
channel.addGroup(TEST_GROUP, 1, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, listener);
channel.setEnabled(false);
channel.setEnabled(true);
/* Release call to mock ingestion. */
beforeCallSemaphore.release();
/* Wait for callback ingestion. */
afterCallSemaphore.acquireUninterruptibly();
/* Verify handling error was ignored. */
verify(listener, never()).onFailure(any(Log.class), eq(mockException));
verify(listener).onFailure(any(Log.class), argThat(new ArgumentMatcher<Exception>() {
@Override
public boolean matches(Object argument) {
return argument instanceof CancellationException;
}
}));
}
use of com.microsoft.azure.mobile.CancellationException in project mobile-center-sdk-android by Microsoft.
the class DefaultChannel method shutdown.
@Override
public synchronized void shutdown() {
suspend(false, new CancellationException());
try {
MobileCenterLog.debug(LOG_TAG, "Wait for persistence to process queue.");
mPersistence.waitForCurrentTasksToComplete(SHUTDOWN_TIMEOUT);
} catch (InterruptedException e) {
MobileCenterLog.warn(LOG_TAG, "Interrupted while waiting persistence to flush.", e);
}
}
use of com.microsoft.azure.mobile.CancellationException in project mobile-center-sdk-android by Microsoft.
the class DefaultChannelRaceConditionTest method disabledWhileHandlingIngestionSuccess.
@Test
public void disabledWhileHandlingIngestionSuccess() throws Exception {
/* Set up mocking. */
final Semaphore beforeCallSemaphore = new Semaphore(0);
final Semaphore afterCallSemaphore = new Semaphore(0);
Persistence mockPersistence = mock(Persistence.class);
when(mockPersistence.countLogs(anyString())).thenReturn(1);
when(mockPersistence.getLogs(anyString(), eq(1), anyListOf(Log.class))).then(getGetLogsAnswer(1));
when(mockPersistence.getLogs(anyString(), eq(CLEAR_BATCH_SIZE), anyListOf(Log.class))).then(getGetLogsAnswer(0));
DatabasePersistenceAsync mockPersistenceAsync = spy(new DatabasePersistenceAsync(mockPersistence));
whenNew(DatabasePersistenceAsync.class).withArguments(mockPersistence).thenReturn(mockPersistenceAsync);
IngestionHttp mockIngestion = mock(IngestionHttp.class);
when(mockIngestion.sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class))).then(new Answer<Object>() {
@Override
public Object answer(final InvocationOnMock invocation) throws Throwable {
new Thread() {
@Override
public void run() {
beforeCallSemaphore.acquireUninterruptibly();
((ServiceCallback) invocation.getArguments()[3]).onCallSucceeded("");
afterCallSemaphore.release();
}
}.start();
return mock(ServiceCall.class);
}
});
/* Simulate enable module then disable. */
DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), mockPersistence, mockIngestion);
Channel.GroupListener listener = mock(Channel.GroupListener.class);
channel.addGroup(TEST_GROUP, 1, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, listener);
channel.setEnabled(false);
channel.setEnabled(true);
/* Release call to mock ingestion. */
beforeCallSemaphore.release();
/* Wait for callback ingestion. */
afterCallSemaphore.acquireUninterruptibly();
/* Verify handling success was ignored. */
verify(listener, never()).onSuccess(any(Log.class));
verify(listener).onFailure(any(Log.class), argThat(new ArgumentMatcher<Exception>() {
@Override
public boolean matches(Object argument) {
return argument instanceof CancellationException;
}
}));
}
Aggregations