contact-hook: less destructive catch-up on-sub

(Re)subscribing gets us a %contacts update, containing the full set of
contacts as it currently exists.

Previously, we would fully delete our local state, only to recreate it
using the data from the update.

Now, we never delete existing data, instead only creating if we don't
have it yet, and adding, removing or recreating contacts if they
changed.

In the future, we'll want an easy way to turn two contacts into an %edit
diff, to let us apply correct semantics to individual contacts, too.
This commit is contained in:
Fang 2020-03-27 14:21:03 +01:00
parent 4551c74e3a
commit 058dcdf100
No known key found for this signature in database
GPG Key ID: EB035760C1BBA972

View File

@ -273,13 +273,38 @@
%contacts
=/ owner (~(got by synced) path.fact)
?> =(owner src.bol)
%+ weld
:~ (contact-poke [%delete path.fact])
(contact-poke [%create path.fact])
=/ have-contacts=(unit contacts)
(contacts-scry path.fact)
?~ have-contacts
:: if we don't have any contacts yet,
:: create the entry, and %add every contact
::
:- (contact-poke [%create path.fact])
%+ turn ~(tap by contacts.fact)
|= [=ship =contact]
(contact-poke [%add path.fact ship contact])
:: if we already have some, decide between %add, %remove and recreate
:: on a per-contact basis
::
%- zing
%+ turn
%~ tap in
%- ~(uni in ~(key by contacts.fact))
~(key by u.have-contacts)
|= =ship
^- (list card)
=/ have=(unit contact) (~(get by u.have-contacts) ship)
=/ want=(unit contact) (~(get by contacts.fact) ship)
?~ have
[(contact-poke %add path.fact ship (need want))]~
?~ want
[(contact-poke %remove path.fact ship)]~
?: =(u.want u.have) ~
::TODO probably want an %all edit-field that resolves to more granular
:: updates within the contact-store?
:~ (contact-poke %remove path.fact ship)
(contact-poke %add path.fact ship u.want)
==
%+ turn ~(tap by contacts.fact)
|= [=ship =contact]
(contact-poke [%add path.fact ship contact])
::
%add
=/ owner (~(got by synced) path.fact)