← Back to team overview

gtg-contributors team mailing list archive

Re: [Gtg-gsoc] Invernizzi - GSoC code review

 

I should explain how I think the solution 1 task/x backend would work at
the architecture level.
I'll need a lot of attention, sorry :)

Let's start from the bottom: How is a backend structured. I'm talking  
about r/w backends here. Read only are simpler and import and export   
are even simpler. 
A backend will have a set of attached tags (tags for which 
the backend is entitled to store the task. the "all-tasks" is a special
kind of tag here, so that case is covered)                             
A backend will receive from GTG the list of tasks (I'll call those
gtg_tasks) it should worry about.
(This information is passed via the Backend.sync_function explained
later).
Each of these gtg_tasks has its own id and modification time, and that's
all that matters to us. 
We don't know we're inside GTG, we don't know what a Datastore is, etc...

A backend will fetch from its remote source of tasks a set of
remote_tasks, each with their own id (which we cannot change) and
modification time.
So far it should be clear: a backend has two sets of tasks to match.

Now, I'm interested in how to create a relationship between those sets,
in order to discover which tasks are really the same task stored in two
different forms (one on the backend, one inside GTG).
We have two cases:
i) First (sync) run
ii) Later run

On first run (i), things are easy: GTG_tasks and Remote_tasks are two
sets without intersection, in the sense that the GTG_tasks have never
been stored in the backend and vice versa. Therefore, we simply create a
GTG_task for every Remote_tasks and vice versa.
*you can skip  this part*
In reality, a previous attempt to sync may have happened, so instead
of blindly creating copies for each task, in the RTM plugin I tried to
match tasks with the same title before, so that we avoid duplicates.
That works pretty well, apparently.
*Now you read again*

In order to remember the relationships that intercur between GTG_tasks
and Remote_tasks, a backend will maintain a list of sync_memes, of this
form:
class sync_meme:
   remote_id
   gtg_id
   last_synced_modification_time_for_remote
   last_synced_modification_time_for_gtg

every sync_meme ties a remote_task to a gtg_task (via the remote_id and
gtg_id fields).
On the first run, after creating the counterpart for each
task, the backend records the modification time for both
tasks (in the last_synced_modification_time_for_remote and
last_synced_modification_time_for_gtg fields).
This list of sync_meme is saved by the backend when the backend is shut
down, and restored on initialization.
 It constitutes its memory of which tasks are linked.

Now, let's restart GTG and analyze a later run (ii).
The backend will have again two sets of tasks (remote_tasks and
gtg_tasks), and he has to find out what has changed
To do so, first he checks the current gtg_task ids with the ones stored
in the sync_memes. Ids which are not present in the sync_memes are the
new tasks in GTG, while ids which have disappeared will be tasks which
have been removed from GTG.
The backend will add a new task in the Remote_tasks for each new GTG
task (and create a proper sync_meme) and
 **the backend will remove the corresponding remote task for each
removed GTG task**. What I'm saying here is that once a task is removed,
we don't care if it has been updated in the remote_tasks after the
removal in GTG. It has been removed, so we remove it. This works
perfectly well in the RTM plugin, and it simplifies things a lot.

We do the same process for the remote_tasks (so, we find out the new and
removed tasks, and we act as before).

Now, we take all the task which have not been parts of the previous
treatments. These tasks are the ones for which the relationship described
in the sync_meme still stands.
For every couple of tasks, we check the gtg_task modification time with
the one stored in the sync_meme, and we do the same for the remote_task.
If the modification times are equal or older than the sync_meme's stored
ones, we do nothing (neither task has changed).
If the modification time of just one of those tasks is sooner than the
one stored in the sync_meme, that task has been modified, so we copy
that task over the other.
If the modification time of both tasks are sooner than the stored ones,
we confront them and the newer gets to be copied over the other.

This is, basically, how the RTM plugin currently operates. This process
of syncing is in polling, so every once in a while a sync gets started.
The user may optionally force it, via a nice button that he can smash at
will.


Now that you know how backends work in my idea, let's proceed up to our
second part of the "journey", this time inside GTG.
Let's start GTG again.
Backends are somehow initialized (we don't care about that) and passed
to the Datastore.
The Datastore knows only two things about each backend:
A) a unique id
B) tags that are attached to the backend 

The Datastore main function is to come into action when on of these three events occur:
1)a task is created
2) a task is deleted
3) task's tags change

When a task is created (1), the Datastore finds out which backends
should store that task (based on the attached tags B) and creates a
relationship between the task and the backend. This relationship is
nothing more that a Backend.sync_function, that the task should call
when it is modified. Every backend that matches the requirements will
provide its sync_function to the task. Therefore, the task maintains a
list of sync_functions, each of which have to be called when changes
occur (more on this later, as its critical - bear with me).

When a task is deleted (2), it is simply deleted from all backends. The
backends will then propagate the deletion to the remote services.

When a task's tags change, the task is removed from all the backends
which do not have the correct tags to be entitled to store that anymore,
and it's added to the backends which now fulfill the requirements.



Now, suppose the user changes one task. The task calls all its
sync_functions to notify the change. The representation of the gtg_task
in the backend will be updated, along with its modification time. If the
task modification time is newer that the one stored in the backend, the
task will be synced remotely on the next sync.

What happens if the backend stumbles in a remote_task which is newer
than the gtg_task? Via the Requester, he checks that the GTG task is
really older (double checking, just to be sure - it's not really needed)
and it updates that, copying *the remote_task modification time to the
task modification time*. The task will then call a sync, so that the
change is propagated on other backends.


I hope I have been clear. For the user case you'll have to wait I get a
good night&morning rest :).
  Luca





























On Sat, May 22, 2010 at 03:04:34PM -0700, Bryce Harrington wrote:
> > Usercase:
> > Sandy has her GTG list.
> > - eat pizza
> >   - buy pizza
> >     - something else
> > Sandy keeps her shopping list on her phone. Therefore, before going to the supermarket, she tags buy pizza @RTM.
> > Now, RTM does not support subtasks. What happen to "something else"?
> 
> Thought of a few more launchpad use case ideas after sending the last email...
> These really don't add much to the discussion, and are mostly predicated
> on a read-write launchpad backend, but thought I'd throw them out to
> help stimulate thought.
> 
> Btw, I'm not saying we *should* do these things, only that if such
> things *could* be done in some fashion with gtg.
> 
> 
> 0.  For all gtg bugs in status 'New', Bob creates individual tasks to
> review and triage them.  For each task, he loads the bug in firefox to
> look at and work on, then marks it to status Confirmed in launchpad, and
> closes the task in gtg.
> 
> 1.  Arthur retrieves a listing of all unassigned confirmed bugs, and
> browses them, selecting subset to add to his task list.  Launchpad is
> then updated to mark those bugs as assigned to him.
> 
> 2.  Arthur imports 42 assigned launchpad bug reports.  He decides to
> focus on 2 this week starting tomorrow.  He selects the other 40 and set
> their start date to next week.
> 
> 3.  The next day, the 2 tasks/bugs become started and appear in Arthur's
> WorkView.  Launchpad is automatically updated to put the bugs into 'In
> Progress' status.
> 
> 4.  For the first bug, Arthur decides to wait on working on it until
> after he returns from a developer conference, so reschedules it for 3
> weeks.  Launchpad is automatically updated to put the bug status back to
> 'Triaged'.
> 
> 5.  For the second bug, Arthur notices that the reporter did not test
> the correct version of the code.  He adds a task for a triager
> (e.g. Bob) to walk the reporter through the process of doing this
> testing.  This task is published to launchpad so any bug triager using
> gtg can spot it and assign it to themselves.
> 
> Bryce
> 
> 
> 

Attachment: signature.asc
Description: Digital signature


References