Put it all in one dataspace

This commit is contained in:
Emery Hemingway 2023-07-26 18:06:38 +01:00
parent 85648f4956
commit c71ad44e3d
2 changed files with 60 additions and 86 deletions

View File

@ -9,80 +9,55 @@ import ./simplex_bot_actor/[message_types, simple_types, websockets]
type
Value = Preserve[void]
Args {.preservesDictionary.} = object
dataspace: Cap
url: string
ContactSubscription {.preservesDictionary.} = object
contact: Attributes
Internal* {.preservesRecord: "internal".} = object
dataspace: Cap
Contact = ref object
# TODO: does a Contact get its own facet
dataspace: Cap
capHandle, summaryHandle, profileHandle, chatItemHandle: Handle
Group = ref object
dataspace: Cap
capHandle, infoHandle: Handle
# ContactAssertion = simple_types.ContactAssertion[Cap]
ContactAssertion {.preservesRecord: "contact".} = object
id: int
cap: Cap
info: Attributes
GroupAssertion {.preservesRecord: "group".} = object
id: int
cap: Cap
info: Attributes
proc updateAttrs(contact: Contact; turn: var Turn; attrs: Attributes) =
replace(turn, contact.dataspace, contact.summaryHandle, attrs)
var profile = attrs.getOrDefault(Symbol"profile")
if not profile.isFalse:
replace(turn, contact.dataspace, contact.profileHandle, profile)
ChatItemAssertion {.preservesRecord: "chat-item".} = object
id: int
info: Attributes
proc updateAttrs(group: Group; turn: var Turn; info: Attributes) =
replace(turn, group.dataspace, group.infoHandle, info)
ContactSubscription {.preservesDictionary.} = object
contact: Attributes
ChatItemMeta {.preservesDictionary.} = object
itemId: int
proc `%`(bindings: sink openArray[(string, Pattern)]): Pattern =
## Sugar for creating dictionary patterns.
patterns.grabDictionary(bindings)
proc bootContact(turn: var Turn; intern: Cap; contactId: int): Contact =
let contact = Contact(dataspace: newDataspace(turn))
block:
let pat = grabRecord("recv", %{"resp": %{"contactUpdated": %{
"fromContact": %{"contactId": grab(contactId)},
"toContact": grab(),
}}})
onMessage(turn, intern, pat) do (attrs: Attributes):
updateAttrs(contact, turn, attrs)
proc grabResp(obj: Pattern): Pattern =
grabRecord("recv", %{ "resp": obj })
block:
let pat = grabRecord("recv", %{"resp": %{"chatItem": %{
"chatInfo": %{"contact": %{"contactId": grab(contactId)}},
"chatItem": grab(),
}}}) # TODO: could update contact profiles from these messages
onMessage(turn, intern, pat) do (attrs: Attributes):
var
msgId = cast[seq[byte]](base64.decode(attrs[Symbol"meta"]["itemSharedMsgId".toSymbol].string))
msg = initRecord("message", Preserve[void](), msgId.toPreserve, attrs[Symbol"content"])
debugEcho "publish message ", msg
contact.chatItemHandle = publish(turn, contact.dataspace, msg)
proc bootClient(turn: var Turn; extern, intern: Cap) =
contact
var contacts = initTable[int, Handle]()
proc updateContact(turn: var Turn; attrs: Attributes) =
var ass: ContactAssertion
if ass.id.fromPreserve(attrs.getOrDefault(Symbol"contactId")):
ass.info = attrs
contacts[ass.id] = replace(turn, extern, contacts.getOrDefault(ass.id), ass)
proc bootGroup(turn: var Turn; intern: Cap; groupId: int): Group =
let group = Group(dataspace: newDataspace(turn))
group
var groups = newTable[int, Handle]()
proc updateGroup(turn: var Turn; attrs: Attributes) =
var ass: GroupAssertion
if ass.id.fromPreserve(attrs.getOrDefault(Symbol"groupId")):
ass.info = attrs
groups[ass.id] = replace(turn, extern, groups.getOrDefault(ass.id), ass)
proc bootClient(turn: var Turn; ds, intern: Cap) =
var
contacts = initTable[int, Contact]()
groups = initTable[int, Group]()
# mapping of contactId to Contact data
var chatItems = newTable[int, Handle]()
proc updateChatItem(turn: var Turn; attrs: Attributes) =
var
ass: ChatItemAssertion
meta: ChatItemMeta
if meta.fromPreserve(attrs.getOrDefault(Symbol"meta")):
ass.id = meta.itemId
ass.info = attrs
chatItems[ass.id] = replace(turn, extern, chatItems.getOrDefault(ass.id), ass)
block:
let dumpStream = openFileStream("/tmp/simplex_bot_actor.log", fmWrite)
@ -92,40 +67,38 @@ proc bootClient(turn: var Turn; ds, intern: Cap) =
write(dumpStream, '\n')
flush(dumpStream)
block: # concats
let pat = grabRecord("recv", %{"resp": %{
block: # contacts
let pat = grabResp(%{
"contactSubscriptions": grab(),
"type": grab"contactSubSummary",
}})
})
debugEcho "grab contacts with ", pat
onMessage(turn, intern, pat) do (subs: seq[ContactSubscription]):
for e in subs:
var id: int
if id.fromPreserve(e.contact[Symbol"contactId"]):
var contact = contacts.getOrDefault(id)
if contact.isNil:
contact = bootContact(turn, intern, id)
contacts[id] = contact
contact.capHandle = publish(turn, ds,
ContactAssertion(id: id, cap: contact.dataspace))
updateAttrs(contact, turn, e.contact)
for sub in subs: updateContact(turn, sub.contact)
block: # groups
let pat = grabRecord("recv", %{"resp": %{"groupInfo": grab()}})
onMessage(turn, intern, pat) do (info: Attributes):
var id: int
if id.fromPreserve(info[Symbol"groupId"]):
var group = groups.getOrDefault(id)
if group.isNil:
group = bootGroup(turn, intern, id)
groups[id] = group
group.capHandle = publish(turn, ds,
GroupAssertion(id: id, cap: group.dataspace))
updateAttrs(group, turn, info)
let pat = grabResp(%{ "groupInfo": grab() })
onMessage(turn, intern, pat) do (groupInfo: Attributes):
updateGroup(turn, groupInfo)
block:
let pat = grabResp(%{ "chatItem": %{ "chatInfo":
%{ "groupInfo": grab() }}})
onMessage(turn, intern, pat) do (groupInfo: Attributes):
updateGroup(turn, groupInfo)
onPublish(turn, ds, ?ContactAssertion) do (contactId: int; cap: Cap):
onPublish(turn, cap, %{"localDisplayName": grab()}) do (name: string):
onPublish(turn, cap, %{"image": ?MIMEData}) do (typ: Symbol, data: seq[byte]):
debugEcho "contact ", name, " has an image of ", data.len, " bytes"
block: # messages
let pat = grabResp(%{ "chatItem": %{ "chatInfo": %{ "chatItem": grab() }}})
onMessage(turn, intern, pat) do (chatItem: Attributes):
updateChatItem(turn, chatItem)
onPublish(turn, extern, ContactAssertion ? {0: grab()}) do (contactId: int):
onPublish(turn, extern, ContactAssertion ? {
0: grab(contactId), 1: %{ "localDisplayName": grab() }}) do (name: string):
debugEcho "contact ", contactId, " is ", name
type Args {.preservesDictionary.} = object
dataspace: Cap
url: string
runActor("eris_actor") do (root: Cap; turn: var Turn):
# connectStdio(root, turn)

View File

@ -50,6 +50,7 @@ proc spawnWebsocketJsonActor*(turn: var Turn; ds: Cap): Actor {.discardable.} =
of Pong, Cont:
discard
of Close:
stderr.writeLine "closed connection with ", url
retract(turn, handle)
stop(turn)
return