|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
public interface HighRepJobPolicy
A policy for high replication job application. Implementations can decide whether or not a new job should apply and whether or not a job that initially failed to apply should roll forward on subsequent attempts.
Some implementation details that are pertinent to implementors of this interface:
When a user performs a non-transactional Put(), a non-transactional
Delete(), or a Commit() of a transaction to which at least one transactional
Put() or Delete() was added, the LocalDatastoreService
attempts to
apply that mutation using a job associated with the entity group of the
mutation. The decision of whether or not the job should apply is delegated
to shouldApplyNewJob(Key)
.
Unapplied jobs may be rolled forward in two ways: when the consistency model dictates it, and when an entity group is groomed. We'll discuss these in turn.
When the high replication consistency model guarantees that users will see the most up-to-date values for an entity group, we roll forward unapplied jobs before returning any data from the entity group. Specifically, a transactional Get() will roll forward any unapplied jobs in the entity group, as will a non-transactional Get() with the read policy set to STRONG (the default). A transactional Query (which is by definition an ancestor Query and therefore a scan over the entities in a single entity group) will also roll forward any unapplied jobs associated with the entity group of the query before the query executes.
Unapplied jobs can also be rolled forward when the entity group with these
jobs is groomed. In production, the groomer is a background process that
is continuously scanning and rolling forward unapplied jobs. We considered
implementing something similar, but it's nearly impossible to write tests
in an environment where you have a background process randomly adjusting
your persistent state, so we opted for a different approach: the local
datastore groomer looks at all unapplied jobs on every Get() and every
Query(), and for each unapplied job, consults
shouldRollForwardExistingJob(Key)
to see if that
job should be rolled forward. This simulates grooming, but in
a deterministic manner that makes testing much more straightforward.
Note, however, that when the groomer rolls these jobs forward, it does so in such a way that the result of the operation being performed is not affected. This is important, because it guarantees that when a job fails to apply, a user who reads the entity group without any strong consistency guarantees will always see the "old" version of the data in the entity group at least once. Without this guarantee we would have jobs that failed to apply but whose failure was invisible, which defeats the purpose of what we're trying to simulate.
Method Summary | |
---|---|
boolean |
shouldApplyNewJob(com.google.appengine.api.datastore.Key entityGroup)
|
boolean |
shouldRollForwardExistingJob(com.google.appengine.api.datastore.Key entityGroup)
|
Method Detail |
---|
boolean shouldApplyNewJob(com.google.appengine.api.datastore.Key entityGroup)
entityGroup
- A unique identifier for the entity group.
true
if the new job should apply according to the policy,
false
otherwise.boolean shouldRollForwardExistingJob(com.google.appengine.api.datastore.Key entityGroup)
entityGroup
- A unique identifier for the entity group.
true
if the existing job should roll forward
according to the policy, false
otherwise.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |