| 198 | |
| 199 | |
| 200 | Future<bool> GroupProcess::cancel(const Group::Membership& membership) |
| 201 | { |
| 202 | if (error.isSome()) { |
| 203 | return Failure(error.get()); |
| 204 | } else if (owned.count(membership.id()) == 0) { |
| 205 | // TODO(benh): Should this be an error? Right now a user can't |
| 206 | // differentiate when 'false' means they can't cancel because it's |
| 207 | // not owned or because it's already been cancelled (explicitly by |
| 208 | // them or implicitly due to session expiration or operator |
| 209 | // error). |
| 210 | return false; |
| 211 | } |
| 212 | |
| 213 | if (state != READY) { |
| 214 | Cancel* cancel = new Cancel(membership); |
| 215 | pending.cancels.push(cancel); |
| 216 | return cancel->promise.future(); |
| 217 | } |
| 218 | |
| 219 | // TODO(benh): Only attempt if the pending queue is empty so that a |
| 220 | // client can assume a happens-before ordering of operations (i.e., |
| 221 | // the first request will happen before the second, etc). |
| 222 | |
| 223 | Result<bool> cancellation = doCancel(membership); |
| 224 | |
| 225 | if (cancellation.isNone()) { // Try again later. |
| 226 | if (!retrying) { |
| 227 | delay(RETRY_INTERVAL, self(), &GroupProcess::retry, RETRY_INTERVAL); |
| 228 | retrying = true; |
| 229 | } |
| 230 | Cancel* cancel = new Cancel(membership); |
| 231 | pending.cancels.push(cancel); |
| 232 | return cancel->promise.future(); |
| 233 | } else if (cancellation.isError()) { |
| 234 | return Failure(cancellation.error()); |
| 235 | } |
| 236 | |
| 237 | return cancellation.get(); |
| 238 | } |
| 239 | |
| 240 | |
| 241 | Future<Option<string>> GroupProcess::data(const Group::Membership& membership) |