Skip to content

Commit 5a5046e

Browse files
committed
Some improvements to the task caches (#4519)
1 parent 7cda863 commit 5a5046e

File tree

2 files changed

+77
-41
lines changed

2 files changed

+77
-41
lines changed

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/TaskCompletionSourceCache.java

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ Task<T> getOrCreateTaskFromCompletionSource(TaskCompletionSourceProducer<T> prod
5959
TaskCompletionSource<T> taskCompletionSource = new TaskCompletionSource<>();
6060
sequentialExecutor.execute(
6161
() -> {
62-
if (!isOngoing(cachedTaskCompletionSource)) {
62+
if (cachedTaskCompletionSource == null
63+
|| cachedTaskCompletionSource.getTask().isComplete()) {
6364
cachedTaskCompletionSource = producer.produce();
6465
}
6566
TaskUtils.shadowTask(taskCompletionSource, cachedTaskCompletionSource.getTask());
@@ -68,36 +69,62 @@ Task<T> getOrCreateTaskFromCompletionSource(TaskCompletionSourceProducer<T> prod
6869
}
6970

7071
/**
71-
* Sets the result on the cached {@link TaskCompletionSource}, if there is one and it is not
72-
* completed.
72+
* Sets the result on the cached {@link TaskCompletionSource}.
73+
*
74+
* <p>The task must be created using {@link #getOrCreateTaskFromCompletionSource} before calling
75+
* this method.
76+
*
77+
* @return A task that resolves when the change is applied, or fails with {@link
78+
* IllegalStateException} if the task was not created yet or was already completed.
7379
*/
7480
Task<Void> setResult(T result) {
75-
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();
76-
sequentialExecutor.execute(
77-
() -> {
78-
if (isOngoing(cachedTaskCompletionSource)) {
79-
cachedTaskCompletionSource.setResult(result);
80-
}
81-
});
82-
return taskCompletionSource.getTask();
81+
return executeIfOngoing(() -> cachedTaskCompletionSource.setResult(result));
8382
}
8483

8584
/**
8685
* Sets the exception on the cached {@link TaskCompletionSource}, if there is one and it is not
8786
* completed.
87+
*
88+
* <p>The task must be created using {@link #getOrCreateTaskFromCompletionSource} before calling
89+
* this method.
90+
*
91+
* @return A task that resolves when the change is applied, or fails with {@link
92+
* IllegalStateException} if the task was not created yet or was already completed.
8893
*/
8994
Task<Void> setException(Exception e) {
95+
return executeIfOngoing(() -> cachedTaskCompletionSource.setException(e));
96+
}
97+
98+
/**
99+
* Returns a task indicating whether the cached {@link TaskCompletionSource} has been initialized
100+
* and is not yet completed.
101+
*/
102+
Task<Boolean> isOngoing() {
103+
TaskCompletionSource<Boolean> taskCompletionSource = new TaskCompletionSource<>();
104+
sequentialExecutor.execute(
105+
() ->
106+
taskCompletionSource.setResult(
107+
cachedTaskCompletionSource != null
108+
&& !cachedTaskCompletionSource.getTask().isComplete()));
109+
return taskCompletionSource.getTask();
110+
}
111+
112+
private Task<Void> executeIfOngoing(Runnable r) {
90113
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();
91114
sequentialExecutor.execute(
92115
() -> {
93-
if (isOngoing(cachedTaskCompletionSource)) {
94-
cachedTaskCompletionSource.setException(e);
116+
if (cachedTaskCompletionSource == null) {
117+
taskCompletionSource.setException(
118+
new IllegalStateException(
119+
"Tried to set exception before calling getOrCreateTaskFromCompletionSource()"));
120+
} else if (cachedTaskCompletionSource.getTask().isComplete()) {
121+
taskCompletionSource.setException(
122+
new IllegalStateException("Tried to set exception on a completed task"));
123+
} else {
124+
r.run();
125+
taskCompletionSource.setResult(null);
95126
}
96127
});
97128
return taskCompletionSource.getTask();
98129
}
99-
100-
private static <T> boolean isOngoing(TaskCompletionSource<T> taskCompletionSource) {
101-
return taskCompletionSource != null && !taskCompletionSource.getTask().isComplete();
102-
}
103130
}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/UpdateTaskCache.java

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ UpdateTask getOrCreateUpdateTask(UpdateTaskProducer producer) {
6363
UpdateTaskImpl impl = new UpdateTaskImpl();
6464
sequentialExecutor.execute(
6565
() -> {
66-
if (!isOngoing(cachedUpdateTaskImpl)) {
66+
if (cachedUpdateTaskImpl == null || cachedUpdateTaskImpl.isComplete()) {
6767
cachedUpdateTaskImpl = producer.produce();
6868
}
6969
impl.shadow(cachedUpdateTaskImpl);
@@ -72,50 +72,59 @@ UpdateTask getOrCreateUpdateTask(UpdateTaskProducer producer) {
7272
}
7373

7474
/**
75-
* Sets the exception on the cached {@link UpdateTaskImpl}, if there is one and it is not
75+
* Sets the progress on the cached {@link UpdateTaskImpl}, if there is one and it is not
7676
* completed.
77+
*
78+
* <p>The task must be created using {@link #getOrCreateUpdateTask} before calling this method.
79+
*
80+
* @return A task that resolves when the change is applied, or fails with {@link
81+
* IllegalStateException} if the task was not created yet or was already completed.
7782
*/
7883
Task<Void> setProgress(UpdateProgress progress) {
79-
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();
80-
sequentialExecutor.execute(
81-
() -> {
82-
if (isOngoing(cachedUpdateTaskImpl)) {
83-
cachedUpdateTaskImpl.updateProgress(progress);
84-
}
85-
});
86-
return taskCompletionSource.getTask();
84+
return executeIfOngoing(() -> cachedUpdateTaskImpl.updateProgress(progress));
8785
}
8886

8987
/**
9088
* Sets the result on the cached {@link UpdateTaskImpl}, if there is one and it is not completed.
89+
*
90+
* <p>The task must be created using {@link #getOrCreateUpdateTask} before calling this method.
91+
*
92+
* @return A task that resolves when the change is applied, or fails with {@link
93+
* IllegalStateException} if the task was not created yet or was already completed.
9194
*/
9295
Task<Void> setResult() {
93-
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();
94-
sequentialExecutor.execute(
95-
() -> {
96-
if (isOngoing(cachedUpdateTaskImpl)) {
97-
cachedUpdateTaskImpl.setResult();
98-
}
99-
});
100-
return taskCompletionSource.getTask();
96+
return executeIfOngoing(() -> cachedUpdateTaskImpl.setResult());
10197
}
10298

10399
/**
104100
* Sets the exception on the cached {@link UpdateTaskImpl}, if there is one and it is not
105101
* completed.
102+
*
103+
* <p>The task must be created using {@link #getOrCreateUpdateTask} before calling this method.
104+
*
105+
* @return A task that resolves when the change is applied, or fails with {@link
106+
* IllegalStateException} if the task was not created yet or was already completed.
106107
*/
107108
Task<Void> setException(FirebaseAppDistributionException e) {
109+
return executeIfOngoing(() -> cachedUpdateTaskImpl.setException(e));
110+
}
111+
112+
private Task<Void> executeIfOngoing(Runnable r) {
108113
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();
109114
sequentialExecutor.execute(
110115
() -> {
111-
if (isOngoing(cachedUpdateTaskImpl)) {
112-
cachedUpdateTaskImpl.setException(e);
116+
if (cachedUpdateTaskImpl == null) {
117+
taskCompletionSource.setException(
118+
new IllegalStateException(
119+
"Tried to set exception before calling getOrCreateUpdateTask()"));
120+
} else if (cachedUpdateTaskImpl.isComplete()) {
121+
taskCompletionSource.setException(
122+
new IllegalStateException("Tried to set exception on a completed task"));
123+
} else {
124+
r.run();
125+
taskCompletionSource.setResult(null);
113126
}
114127
});
115128
return taskCompletionSource.getTask();
116129
}
117-
118-
private static boolean isOngoing(UpdateTask updateTask) {
119-
return updateTask != null && !updateTask.isComplete();
120-
}
121130
}

0 commit comments

Comments
 (0)