Add some helpful logging to ndb_persistence
Add internal persist marker function to Async
Make Context.task_ids into a Python property

Rather than a "hidden" member, make task ids into a read-only property
so that the persistence engine can easily access the list of ids to
check.
Add simple Async Marker logic to ndb_persistence engine

Add an entity for use when marking an Async complete and update the
store_async_marker function to create a complete marker entity.
Add simple context completion checker to ndb persistence

Add a very basic context completion checker to ndb_persistence engine.
The checker fetches batches of 10 keys to search for Async markers, if
any marker is found to not exist the checker bails out early.
Set context checker on Asyncs if defined on Context

If a persistence engine is defined for a Context, set its context completion
checker on all contained Async jobs.
Add infrastructure for Context events
Make ndb_persistence execute Context's complete event
Call persist_marker for Async jobs

This is not in the correct spot.  It should probably check if a
persistence engine is defined before being called.  It might also be the
case that this logic should be handled fully within the persistence
engine.
Remove persist marker logic from Async

The marker persistence belongs to the persistence layer, since it might
be very implementation dependent.  This would allow, for example, a
simple in-memory (or memcache) counter to be used if desired.
Implement marker persistence in ndb persistence engine

When checking if a context is complete, persist a marker indicating that
job has run.