Skip to content

Instantly share code, notes, and snippets.

@marcooliveira
Last active January 7, 2019 12:32
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 marcooliveira/fa5c31aded5b69c9c7deff5b73351729 to your computer and use it in GitHub Desktop.
Save marcooliveira/fa5c31aded5b69c9c7deff5b73351729 to your computer and use it in GitHub Desktop.
peer-base collaboration lifecycle

Collaboration Lifecycle

Collaborations are the foundation for your app state, enabling you to share this state across devices and users.

Collaborations are a combination of state and channels that are used to transport changes to the state, and each collaboration goes through 4 stages in their lifecycle.

Collaborations are a construct that happens simultaneously in any device or instance collaborating in it, also known as peers, and are identified by a name, which should be universally unique. These peers might be connected to each other or not, and collaborations merge once they find each other.

This guide is intended for both developers and designers, laying down a set of best practices for UX and UI. There is a glossary in the bottom, should you find some term that's not clear.

1. The lifecycle

Collaborations go through 4 different stages in their lifecycle, always in the same order, and in a circular fashion:

inactivestartingactivestoppinginactive

TODO: replace with nice circular diagram, with inactive on top, going clockwise, with starting on the right, active on the bottom, and stopping on the left.

  • inactive: both the initial and final stage of a collaboration, during which no changes are made.
  • starting: peer-base is looking for other peers and pre-existing state, and the collaboration is not yet ready.
  • active: the collaboration is ready, and the application should be fully interactive, accepting both local and peer changes.
  • stopping: peer-base is closing any existing connections related to the collaboration, and no longer accepting local or peer changes. There can be explicit and implicit stops.

It's important to understand the 4 stages of a collaboration, as it has implications on the UX of your app, the key one being that your app should only become interactive once the collaboration is active.

Of course, each application has specific requirements regarding consistency and availability, which is why you, as a developer and designer, can tweak these policies, in order to control how a collaboration behaves, namely how quickly it becomes active.

Below a bit more detail on the stages and policies you can control.

TODO: an in detail diagram was also being drawn here, although we've come to realise that it's not yet completely accurate, and it's hard to illustrate parallel processes, like the discovery. Something to discuss.

1.1 Starting

While a collaboration is starting, the interface should not accept any modifications, since there is no guarantee that the collaboration is ready. During this period, peer-base is looking for other peers (collaborators) and any pre-existing state, so the user should be presented with some kind of loading interface, if this process takes over 300ms.

TODO: should we programmatically enforce this policy of not allowing changes until the collaboration has become active?

TODO: include what indicates that the collaboration has moved to active. Does it emit a specific event? If so, what parameters does it present?

1.1.1 Behind the Scenes

Collaborations are a combination of state and channels that are used to transport changes to the state. This means that when starting a collaboration, peer-base will try to connect to a discovery network, on which peers meet and exchange state and state changes.

When starting a collaboration, peer-base is deciding whether the collaboration is going to be resumed, joined or initialised:

  • resume: found state locally, resuming from there.
  • join: found state in peers, and loads it, merging with any local state.
  • initialise: didn't find state locally or in peer, initialises it.

If peer-base is unable to do discovery or load pre-existing state, it will initialise a new state. If, later on, another peer is found, with its own state, the two states will merge in a conflict free fashion.

Note that peer discovery and state discovery can happen in parallel, as other peers are continuously being discovered.

Once the consistency and availability policies are met, the collaboration moves to the active stage. For more details on how you can control these policies, check Tweaking "starting" below.

1.1.2 Tweaking "starting"

TODO: need to review the set of options below, give them a good identifier, which can be referred to both in high level conversation and in code.

  • Peer discovery:
    • rendez-vous connection timeout
    • discovery timeout
  • State discovery:
    • state discovery timeout

How you tweak the collaboration is totally up to what you, and heavily depends on what type of application you're developing:

  • Lazy loading: Some collaborations are less destructive, if the user starts affecting state before loading previously existing state. Ie., a notepad dapp might prioritise immediate interactivity, and eventually merge existing state in a safer (non-destructive) fashion, like appending or prepending both texts. This would be fine tuned by you upon collaboration creation, with a very low, or zero timeout for state discovery and state loading.
  • Eager loading: Other collaborations are more destructive, and might require a greater degree of guarantee of consistency of previously existing state, and you would provide more conservative timeout values or other criteria, to guarantee consistency. This could even mean prompting the user to confirm that they want to proceed even though other peers and previous state was unable to load.

TODO: We could allow the developer to provide the parameters, or even provide a callback, allowing for more elaborate and fully custom decision. This callback would receive a predefined set of parameters, like durations of specific things, like peer-discovery-duration, state-discovery-duration, peer list, among other things. This would be a well documented structure, and the callback would return a boolean deciding whether to change to active stage or not. This callback could be triggered by several things, like peer discovery, periodically, and/or others. We could also instead allow the developer to call some function that forces the stage change. Decision functions and configurations (timeout, number of peers, etc) can apply both to discovery and state loading.

1.1.3 Events

When starting, a collaboration may trigger events. Some of these events should only be used for debugging, or internally tracking what's happening, and should not be made apparent to the user, as they will provide a degree of detail too deep, confusing most users.

Below a compreensive list of events:

Event Debugging only Description
finding-state Peer-base is looking for previously existing state, both locally and in peers.
membership-join A new peer joined the membership.

TODO: need to review the events above, and make a compreensive list, making sure we're exposing the right ones and have an ergonomic api and naming system.

TODO: some events, like membership changed will be emitted throughout several stages of the collaboration. Might make sense having a section dedicated to events, regardless of the stage, and instead just have a column in the table stating to which stages the event applies.

1.2 Active

An active collaboration means that the interface should be interactive and accepting modifications. During this period, peer-base is still looking for other peers (collaborators) and accepting state changes from peers, which are merged in a conflict free fashion by the collaboration.

Local changes will be communicated to every connected peer, which eventually acknowledge the reception of these changes, and vice-versa.

A collaboration might leave the active stage both explicitely and implicitely. Check 1.3 Stopping for more details on this.

1.2.1 Behind the Scenes

During the active stage, both peer and state discovery continue to happen, which means that at any time, any of the following might happen:

  • Discovery:
    • Peers will join.
    • Peers will leave.
    • Some peers will join with changes that you don't have.
    • Some peers will join without changes that you have.
    • Some peers will be in sync with you.
  • State changing:
    • Local state is changed, then sent to peers, and acknowledged.
      • Some peers might never acknowledge.
    • Other peers produce changes, which are sent to you, and then you need to acknowledge.

TODO: need to make sure that the list above is compreensive, and edge cases are not forgotten, and then define UX recommendations on which scenarios should be represented in the UI.

1.2.2 Tweaking active

TODO: are there any tweaks we could allow the developer and designer to set?

1.2.3 Events

TODO: Some events will be active specific, but most will not. Should probably have a separate section for events.

1.3 Stopping

A collaboration can be stopping for several reasons, all of which fall into two categories:

  • Explicit stop: programmatically stopping a collaboration.
  • Implicit stop: taking an action that implicitely forces the collaboration to stop.

TODO: Need to review what happens in an explicit and an implicit stop. Should map all scenarios and classify them as explicit or implicit. In scenarios like power failure, is there any clean up in the end that needs to happen before the collaboration actually becomes inactive, or before starting it? Need to have clarity of what happens during stopping, and which scenarious trigger it.

A few scenarios to be included:

  • Exiting browser (process kill, power failure, etc)
  • Closing tab
    • Service Worker
    • IPFS Companion (even though there is incompatibility at the moment)
    • Browser extension (separate process)
    • IPFS daemon REST API
  • Clean browser cache
  • IPFS crash
  • Collaboration.stop()
  • (Any other?)

TODO: Discuss if we should also create clear distinction between the IPFS node and the business logic driving it. Some scenarios of stopping, will stop one but not the other, or sometimes both. Maybe our state machine should make them distinct for clarity, or we need some clear model to communicate this.

TODO: include what indicates that the collaboration has moved to inactive. Does it emit a specific event? If so, what parameters does it present?

1.3.1 Behind the Scenes

TODO:

  • Does it wait for local changes to be sent and acknowledged by other peers?
    • If so, how many?
  • Does it wait for incoming changes to arrive and acknowledge them?
  • Do we want to do something special here in regards to pinning peers?

1.3.2 Tweaking stopping

TODO: are there any tweaks we could allow the developer and designer to set?

1.3.3 Events

TODO: Some events will be stopping specific, but most will not. Should probably have a separate section for events.

1.4 Inactive

TODO: need to answer a lot of the TODOs in stopping in order to complete the inactive stage.

TODO: include what indicates that the collaboration has moved to starting. Does it emit a specific event? If so, what parameters does it present?

1.4.1 Behind the Scenes

1.4.2 Tweaking inactive

2. Glossary

  • Collaboration: combination of state and potential connections that are used to transport mutations.
  • Collaborator: another peer collaborating on a specific collaboration. This can be another user, another device, or simply another instance of the same collaboration.
  • State: the actual data, which evolves through time/mutations.

3. TODO

  • start/stop/starting/stopping collaboration: Should we find better verbs? Start does not apply so well for when we are resuming a collaboration. A few ideas we've discussed, for reference, although none is 100% on point so far:
    • start: unfreeze, join, load, awake
    • starting: joining, loading, awaking
    • active: awaken
    • stop: freeze
    • stopping: ending, leaving, resting, sleeping
    • inactive: stopped, resting, frozen
  • Discuss if we should introduce a few classifications for collaborations, which might require some UI representation, depending on the desired UX:
    • Consistency:
      • Outgoing: all, none, enough, meaning all/none/enough up to date with local changes (enough being a concept to be defined).
      • Incoming: all, none, enough, meaning up to date with peer changes from all/none/enough (enough being a concept to be defined).
    • These can be transient states or not, need to somehow represent when something is happening, like there's currently outgoing or incoming transfers happening or awaiting to be ackowledged, to illustrate that it's working, and not in a dead end.
    • Are there other classifications we need? This consistency, combined with activity feedback seems to comprise both consistency and availability (with the "enough" concept). Maybe need to also represent other peers somehow (membership).
  • Part of this doc is starting to mix with actual code documentation. How far is too far? I'd like to maybe simplify a few things, and refer to actual documentation when necessary.
  • Mostly used UK english, should we change to US english?
  • Should create user friendly handler for scenario in which browser cache or IndexedDB is cleared, and local database is no longer consistent with itself, requiring full reinitialisation. Should this be some kind of required callback upon starting a collaboration, to make sure that users are not left in an inconsistent state, with no way of fixing it without technical know how?
  • Discuss "pinner" concept: Are we going down a dangerous path of semi-centralised? Should we de-prioritise it?
    • Pinning services are a special case of peers, that could have a special graphical representation, but that will reinforce the idea that you need to depend on them.
@pgte
Copy link

pgte commented Jan 7, 2019

@marcooliveira could you rename this file to .md so that we could get a nice preview? :)

@marcooliveira
Copy link
Author

@marcooliveira could you rename this file to .md so that we could get a nice preview? :)

Sorry, did this way too late to notice it! Fixed it 👍

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