A pattern using kasync that I used multiple times is to keep something alive for the duration of the job. I typically solve this using a trailing then clause, where I simply capture a smart pointer, thus ensuring the object lives for the lifetime of the object.
auto synchronizationStore = QSharedPointer<Akonadi2::Storage>::create(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); return replay(*synchronizationStore, type, key, value).then<void>([synchronizationStore](){});
Syntactically l'm not happy with this solution, but I'm also not sure what the proper solution is. One could argue that the store should be passed by smart pointer, so the job that is created internally simply captures the smart pointer where it is required. On the other hand sometimes a reference just results in a nicer API, or I don't want to expose the smart pointer (because a std::shared_ptr is used and I don't want a mix of shared pointers in the API).
Anyways, an alternative would be to have a context for each job, that could i.e. be accessed like this:
KAsync::start<void>(...).addToContext("synchronizationStore", synchronizationStore).exec();
Not high priority, but something to think about.