Skip to content
Snippets Groups Projects
Commit a0910756 authored by Josh Brooks's avatar Josh Brooks
Browse files

Make singleton track groups rather than groupChat manager

parent 8d8c869b
No related branches found
No related tags found
2 merge requests!510Release,!320Make singleton track groups rather than groupChat manager
...@@ -22,57 +22,57 @@ import ( ...@@ -22,57 +22,57 @@ import (
) )
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Group Chat Singleton Tracker // // Group Singleton Tracker //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// groupChatTrackerSingleton is used to track GroupChat objects so that they can be // groupTrackerSingleton is used to track Group objects so that they can be
// referenced by ID back over the bindings. // referenced by ID back over the bindings.
var groupChatTrackerSingleton = &groupChatTracker{ var groupTrackerSingleton = &groupTracker{
tracked: make(map[int]*GroupChat), tracked: make(map[int]*Group),
count: 0, count: 0,
} }
// groupChatTracker is a singleton used to keep track of extant GroupChat objects, // groupTracker is a singleton used to keep track of extant Group objects,
// preventing race conditions created by passing it over the bindings. // preventing race conditions created by passing it over the bindings.
type groupChatTracker struct { type groupTracker struct {
tracked map[int]*GroupChat tracked map[int]*Group
count int count int
mux sync.RWMutex mux sync.RWMutex
} }
// make create a GroupChat from a groupChat.Wrapper, assigns it a unique ID, and // make create a Group from a groupStore.Group, assigns it a unique ID, and
// adds it to the groupChatTracker. // adds it to the groupChatTracker.
func (ut *groupChatTracker) make(gcInt gc.GroupChat) *GroupChat { func (ut *groupTracker) make(g gs.Group) *Group {
ut.mux.Lock() ut.mux.Lock()
defer ut.mux.Unlock() defer ut.mux.Unlock()
id := ut.count id := ut.count
ut.count++ ut.count++
ut.tracked[id] = &GroupChat{ ut.tracked[id] = &Group{
m: gc.NewWrapper(gcInt), g: g,
id: id, id: id,
} }
return ut.tracked[id] return ut.tracked[id]
} }
// get an GroupChat from the groupChatTracker given its ID. // get a Group from the groupChatTracker given its ID.
func (ut *groupChatTracker) get(id int) (*GroupChat, error) { func (ut *groupTracker) get(id int) (*Group, error) {
ut.mux.RLock() ut.mux.RLock()
defer ut.mux.RUnlock() defer ut.mux.RUnlock()
c, exist := ut.tracked[id] g, exist := ut.tracked[id]
if !exist { if !exist {
return nil, errors.Errorf( return nil, errors.Errorf(
"Cannot get GroupChat for ID %d, does not exist", id) "Cannot get Group for ID %d, does not exist", id)
} }
return c, nil return g, nil
} }
// delete removes a GroupChat from the groupChatTracker. // delete removes a Group from the groupTracker.
func (ut *groupChatTracker) delete(id int) { func (ut *groupTracker) delete(id int) {
ut.mux.Lock() ut.mux.Lock()
defer ut.mux.Unlock() defer ut.mux.Unlock()
...@@ -86,32 +86,16 @@ func (ut *groupChatTracker) delete(id int) { ...@@ -86,32 +86,16 @@ func (ut *groupChatTracker) delete(id int) {
// GroupChat is a binding-layer group chat manager. // GroupChat is a binding-layer group chat manager.
type GroupChat struct { type GroupChat struct {
m *gc.Wrapper m *gc.Wrapper
id int
}
// GroupRequest is a bindings-layer interface that handles a group reception.
//
// Parameters:
// - payload - a byte serialized representation of a group.
type GroupRequest interface {
Callback(payload Group)
} }
// LoadOrNewGroupChat creates a bindings-layer group chat manager. // LoadOrNewGroupChat creates a bindings-layer group chat manager.
// //
// Parameters: // Parameters:
// - e2eID - e2e object ID in the tracker. // - e2eID - e2e object ID in the tracker.
// - groupID - GroupChat object ID in the tracker, given from previous call
// to LoadOrNewGroupChat.
// - requestFunc - a callback to handle group chat requests. // - requestFunc - a callback to handle group chat requests.
// - processor - the group chat message processor. // - processor - the group chat message processor.
func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest, func LoadOrNewGroupChat(e2eID int,
processor GroupChatProcessor) (*GroupChat, error) { requestFunc GroupRequest, processor GroupChatProcessor) (*GroupChat, error) {
// Retrieve from singleton
groupChat, err := groupChatTrackerSingleton.get(groupID)
if err == nil { // If present, return group chat manager from singleton
return groupChat, nil
}
// Get user from singleton // Get user from singleton
user, err := e2eTrackerSingleton.get(e2eID) user, err := e2eTrackerSingleton.get(e2eID)
...@@ -121,12 +105,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest, ...@@ -121,12 +105,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
// Construct a wrapper for the request callback // Construct a wrapper for the request callback
requestCb := func(g gs.Group) { requestCb := func(g gs.Group) {
//fixme: review this to see if should be json marshaled. newGroup := groupTrackerSingleton.make(g)
// At the moment, groupStore.DhKeyList is an unsupported requestFunc.Callback(newGroup.id)
// type, it would need a MarshalJson method. If we JSON marshal, change
// JoinGroup implementation and docstring accordingly.
// As for now, it's matching the construction as defined pre-restructure.
requestFunc.Callback(Group{g: g})
} }
// Construct a group chat manager // Construct a group chat manager
...@@ -137,12 +117,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest, ...@@ -137,12 +117,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
} }
// Construct wrapper // Construct wrapper
return groupChatTrackerSingleton.make(gcInt), nil wrapper := gc.NewWrapper(gcInt)
} return &GroupChat{m: wrapper}, nil
// GetID returns the groupChatTracker ID for the GroupChat object.
func (g *GroupChat) GetID() int {
return g.id
} }
// MakeGroup creates a new Group and sends a group request to all members in the // MakeGroup creates a new Group and sends a group request to all members in the
...@@ -226,9 +202,22 @@ func (g *GroupChat) ResendRequest(groupId []byte) ([]byte, error) { ...@@ -226,9 +202,22 @@ func (g *GroupChat) ResendRequest(groupId []byte) ([]byte, error) {
// JoinGroup allows a user to join a group when a request is received. // JoinGroup allows a user to join a group when a request is received.
// //
// Parameters: // Parameters:
// - group - a bindings-level Group object. This is received by GroupRequest.Callback. // - trackedGroupId - the ID to retrieve the Group object within the backend's
func (g *GroupChat) JoinGroup(group Group) error { // tracking system.
return g.m.JoinGroup(group.g) func (g *GroupChat) JoinGroup(trackedGroupId int) error {
// Retrieve group from singleton
grp, err := groupTrackerSingleton.get(trackedGroupId)
if err != nil {
return err
}
// Join group
err = g.m.JoinGroup(grp.g)
if err != nil {
return err
}
return nil
} }
// LeaveGroup deletes a group so a user no longer has access. // LeaveGroup deletes a group so a user no longer has access.
...@@ -288,26 +277,21 @@ func (g *GroupChat) GetGroups() ([]byte, error) { ...@@ -288,26 +277,21 @@ func (g *GroupChat) GetGroups() ([]byte, error) {
return json.Marshal(groupIds) return json.Marshal(groupIds)
} }
// GetGroup returns the group with the group ID. If no group exists, then the // GetGroup returns the Group with the tracked ID from the backend's Group tracker.
// error "failed to find group" is returned.
// //
// Parameters: // Parameters:
// - groupId - the byte data representing a group ID. // - trackedGroupId - the ID to retrieve the Group object within the backend's
// This can be pulled from a marshalled GroupReport. // tracking system.
// Returns: // Returns:
// - Group - the bindings-layer representation of a Group. // - Group - the bindings-layer representation of a group.
func (g *GroupChat) GetGroup(groupId []byte) (*Group, error) { func (g *GroupChat) GetGroup(trackedGroupId int) (*Group, error) {
groupID, err := id.Unmarshal(groupId) // Retrieve group from singleton
group, err := groupTrackerSingleton.get(trackedGroupId)
if err != nil { if err != nil {
return nil, errors.Errorf("Failed to unmarshal group ID: %+v", err) return nil, err
}
grp, exists := g.m.GetGroup(groupID)
if !exists {
return nil, errors.New("failed to find group")
} }
return &Group{g: grp}, nil return group, nil
} }
// NumGroups returns the number of groups the user is a part of. // NumGroups returns the number of groups the user is a part of.
...@@ -323,6 +307,7 @@ func (g *GroupChat) NumGroups() int { ...@@ -323,6 +307,7 @@ func (g *GroupChat) NumGroups() int {
// group chat. // group chat.
type Group struct { type Group struct {
g gs.Group g gs.Group
id int
} }
// GetName returns the name set by the user for the group. // GetName returns the name set by the user for the group.
...@@ -369,9 +354,18 @@ func (g *Group) Serialize() []byte { ...@@ -369,9 +354,18 @@ func (g *Group) Serialize() []byte {
} }
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// Group Chat Processor // Callbacks
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// GroupRequest is a bindings-layer interface that handles a group reception.
//
// Parameters:
// - trackedGroupId - the ID to retrieve the Group object within the backend's
// tracking system.
type GroupRequest interface {
Callback(trackedGroupId int)
}
// GroupChatProcessor manages the handling of received group chat messages. // GroupChatProcessor manages the handling of received group chat messages.
type GroupChatProcessor interface { type GroupChatProcessor interface {
Process(decryptedMessage, msg, receptionId []byte, ephemeralId, Process(decryptedMessage, msg, receptionId []byte, ephemeralId,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment