Closed cheneyang closed 8 years ago
I see multiple angles and am not sure which one suits your underlying requirements, so here they are in the same reply.
Closeable
s) in the middle of the data processing flow in a CompiledRepository that could go nowhere because the flow is cancelled.We've just commit a new feature that allows you to configure a "disposer" (of type Receiver<Object>
) that will be called with the unused intermediate values from the compiled Repository. Give it a try!
observableDeactivated
method.If you have other responsibilities to take care of, chances are you might want to wrap the target Observable and these responsibilities into the same entity, such as a custom Observable that looks like this:
public final class WrappedRepository
extends BaseObservable implements Repository<Blah> {
private final Repository<Blah> targetRepository;
private final Updatable targetRepositoryUpdatable;
public WrappedRepository(... /* params needed to build targetRepository */) {
targetRepository = Repositories.repositoryWithInitialValue(...)
... // prefer building the target repository here, because you can then
// totally "own" it, rather than giving the external world a chance
// to sneak in their updatables.
targetRepositoryUpdatable = () -> dispatchUpdate();
}
protected void observableActivated() {
targetRepository.addUpdatable(targetRepositoryUpdatable);
// any additional activation handling?
}
protected void observableDeactivated() {
targetRepository.removeUpdatable(targetRepositoryUpdatable);
// any additional deactivation handling?
}
public Blah get() {
return targetRepository.get();
}
}
[Just so you're aware, onDeactivation
is not a callback; it is a configuration method for the CompiledRepository.]
onCancel
callback inside the updatable; you know, like a traditional callback interface with 3 methods: onResult
, onError
and onCancel
.Let's discuss "responsibility".
In a typical asynchronous call pattern, the callback is owned by the consumer code of the async method. The consumer code is also the entity that cancels the request -- the async method itself should not actively cancel its requests, or the design feels wrong. This means, at the time the consumer code cancels a request, it can simply handle the cancellation actively rather than using an onCancel
method in the callback. (Please do compare this to the case where the async method could not complete the request due to other entities cancelling: the most proper outcome is an error along the line of a CancellationException
, which the callback will receive via onError
instead.)
In the Agera world, your code owns the updatable; or at least, the process to add the updatable to the observable and remove it from the observable. "Cancellation" is an internal concept only in the CompiledRepository; they only happen if the CANCEL_FLOW
configuration is used in onDeactivation
, and when all updatables are removed from the Repository. This typically means that, at the time of removing the updatable, your code will know that a network request is potentially cancelled, and can actively perform any cleanup work that the Repository's data processing flow might leave behind.
So please try rethinking the design and explore other ways to achieve the same result more directly.
To add to the comment by @maxtroy
If the API used for your request is asynchronous, the cancel method used can only work in a few way. Cancel could either mean
And (3.) In both cases it's common that it also means "don't start if you haven't already started"
Using Agera the first and last will be handled for you anyway, when adding/removing updatables. The second case is handled too; For sync APIs moved to a separate thread using the goTo
operator, a compiled repository can be configured to send an interrupt signal to the thread. This is done using SEND_INTERRUPT. Many standard (sync) Java IO APIs supports this mechanism already, and the operation will be interrupted.
As a last note:
If your API doesn't support sync calls (and I'd def. recommend using sync APIs with Agera!), it means that you're currently forcing the thread used in goTo
to wait for an async response coming back to return the value. Whatever "wait mechanism" used it most likely will throw a checked exception saying the operation has been interrupted. This is where possible cancel methods could be called. Note however that if they themselves aren't interrupting the execution (the second case of the three above) it will have very little value.
Thanks firstly, agera is amzing, but I think there is a flaw: when we do something like network, we always cancel the behavior under some circumstances, we need a callback like onCancel, I know that the
onDeactivation
method may tell us all the updateable was removed, but if I useRepositoryCompiler
to get a Repository, I can not know that because theonDeactivation
is protected, is there anyway to achieve this?