Skip to content

Instantly share code, notes, and snippets.

@dannyroberts
Last active July 7, 2017 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dannyroberts/f184daad468fb7debf10 to your computer and use it in GitHub Desktop.
Save dannyroberts/f184daad468fb7debf10 to your computer and use it in GitHub Desktop.
New idea for extension cases

Can we merge the concepts of extension and delegation cases?

Here's the current breakdown of child, extension, and delegation relationships and their properties, as I see them:

Relationship Can be directly owned sub pulls in super super pulls in sub if open closing super abandons sub
child
extension
delegation

What if we leave child cases unchanged, but merge the concepts of extensions and delegations:

Relationship Can be directly owned sub pulls in super super pulls in sub if open closing super abandons sub
child
extension

Rationale

The current conception of extension cases feels quite awkward to me, as does the fact that it doesn't solve one of the two main use-cases it was conceived for. Perhaps the most awkward part about extension cases is the idea that they don't have any ownership of their own, so assigning them to someone else does nothing.

That seems like a whole set of potential use-cases that we're abandoning. If we allow them to be owned, and allow them to pull in their host, you can still easily simulate the other behavior (can't be owned, doesn't pull in host) by setting the owner_id to ''. In fact, that will likely be the default.

Delegation cases, on the other hand, don't seem to be gaining much by disappearing from the parent's owners' phones. In fact, you may very well want to track progress on your delegation cases, and it's easy to filter out the ones you don't own.

If you adjust extensions and delegations in the way I implied, then they end up being the same thing, at least if you agree with the table.

New Concept of Extension cases

An extension index would then be very much like a child index, except that in addition to pulling its parent in onto phones where it's live, it also:

  • stays on the phones where its parent is live
  • gets pulled from all phones when the parent is closed

In other words, it's tied much more tightly to the parent's lifecycle and always accessible whenever the parent is, while still maintaining the ability (like a child case) to go out in the world and live its own life.

Which cases end up on a user's phone?

I'll introduce two concepts here, available, and live. Available applies globally, where as live only has meaning in the in the context of a given user.

Conceptually, available means not precluded from being on a phone due to a parent being closed (a property of extesion cases).

A case is available if

  • it is open and not an extension case
  • it is open and is the extension of an available case.

Conceptually, live means a case that should be on the user's phone.

In the description below owned means directly owned by the user or owned by a group that the user belongs to.

A case is live if any of the following are true:

  • it is owned and available
  • it has a live child
  • it has a live extension
  • it is the exension of a live case

The mobile phone and HQ may use the same algorithm or different algorithms to arrive at the set of cases that are live as long as they end up with the same result.

Example Traversal algorithm

It's one thing to outline a simple recursive definition as I have above, and another to have an efficient implementation of it. I'll try to outline one here.

This algorithm has the following phases:

  1. Mark relevant cases
  2. Mark available cases
  3. Mark live cases

In order to make the algorithm computationally accessible, we first cast a wide net to include any case that could possibly factor into the liveness calculation, and then limit all future calculations to cases in that set. (This means, for example, we don't have to decide whether every single case in a project is available just to find the set of cases live for a user.) To do that, I'll have to add one more "declaritive style" definition:

A case is relevant if any of the following are true:

  • it is open and owned
  • it has a relevant child
  • it has a relevant extension
  • it is the extension of a relevant case

Now the algorithm is as follows:

Mark relevant cases

  • Mark all open cases owned by the user relevant
  • Traversing all outgoing child and extension indexes, as well as all incoming extension indexes, mark all touched cases relevant.

Mark available cases

  • Mark all relevant cases that are open and have no outgoing extension indexes as available
  • Traversing all incoming extension indexes, mark all touched cases available

Mark live cases

  • Mark all relevant, owned, available cases as live
  • Traversing all outgoing child and extension indexes, as well as incoming extension indexes, mark all touched cases as live.
@proteusvacuum
Copy link

Hey,
Looks good so far! I'm getting much clearer here.
I also made a pass at the algorithm, which I made before your new definitions of relevant / available. Adding it here for discussion purposes -- first time I've done something like this, so probably needs a bunch of tweaking.

Definitions

"Extension" -> owner_id = None
"Delegate" -> owner_id set

Fetch pertinent cases

start with all cases with my owner id (regular, child, delegate)
for all of these cases, recursively pull:

Index Type (direction) Pull Notes
Child (out) Parent "sub pulls in super"
Extension (out) Host case "Sub pulls in super"
Extension (in) Indexing case (iff indexed case is open) "super pulls in sub if open"

Mark:

Case status Mark Notes
Closed Dead
Open with owner_id = None, and extension index outwards ("extension") Abandoned "closing super abandons sub"
Other (open delegates, other open cases) Live "it is owned and available"

Traversal

Pass Pertinent cases Marks Notes
Leaves, breadth first Any live case with extension index and owner id (i.e a 'delegate') Parent -> Live "It has a live extension"
Leaves, breadth first Child cases Parent -> Live "It has a live child"
Roots, depth first Any live case with indexed by an abandoned extension Extension -> Live "It is the extension of a live case"

All live cases should be synced.

@ctsims
Copy link

ctsims commented Oct 30, 2015

Farid and I walked through and realized that the existing algorithm needs to be updated to reflect availability a bit differently.

In the existing algorithm imagine the construct

E -> C

where E is an extension case, and C is an owned case. If E is closed, it is still Live, which isn't desirable. This represents a situation where C is a child, and E is a measurement that was taken incorrectly.

Farid and I walked through and we feel like the crux of the issue is that Availability is being overzealously applied, namely it should be the case that E is available if "it is open and is the extension of an available case.", which is not true here.

Our proposed change is that on the available and liveness walks, the inbound extension traversal is changed to "traverse incoming extension indexes which don't lead to closed cases". Namely that both the flag propagation and the traversal is ceased when the case that they touch is closed.

A closed extension can still be live in this way, but only as the result of being targeted by a relevant as a subcase or something similar.

@millerdev
Copy link

Updated rules for liveness, taking into account @ctsims comment above:

A case is live if any of the following are true:

  • it is owned and available
  • it has a live child
  • it has a live extension
  • it is open and is the exension of a live case

Added text in italics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment