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 (
)
////////////////////////////////////////////////////////////////////////////////
// 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.
var groupChatTrackerSingleton = &groupChatTracker{
tracked: make(map[int]*GroupChat),
var groupTrackerSingleton = &groupTracker{
tracked: make(map[int]*Group),
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.
type groupChatTracker struct {
tracked map[int]*GroupChat
type groupTracker struct {
tracked map[int]*Group
count int
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.
func (ut *groupChatTracker) make(gcInt gc.GroupChat) *GroupChat {
func (ut *groupTracker) make(g gs.Group) *Group {
ut.mux.Lock()
defer ut.mux.Unlock()
id := ut.count
ut.count++
ut.tracked[id] = &GroupChat{
m: gc.NewWrapper(gcInt),
ut.tracked[id] = &Group{
g: g,
id: id,
}
return ut.tracked[id]
}
// get an GroupChat from the groupChatTracker given its ID.
func (ut *groupChatTracker) get(id int) (*GroupChat, error) {
// get a Group from the groupChatTracker given its ID.
func (ut *groupTracker) get(id int) (*Group, error) {
ut.mux.RLock()
defer ut.mux.RUnlock()
c, exist := ut.tracked[id]
g, exist := ut.tracked[id]
if !exist {
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.
func (ut *groupChatTracker) delete(id int) {
// delete removes a Group from the groupTracker.
func (ut *groupTracker) delete(id int) {
ut.mux.Lock()
defer ut.mux.Unlock()
......@@ -86,32 +86,16 @@ func (ut *groupChatTracker) delete(id int) {
// GroupChat is a binding-layer group chat manager.
type GroupChat struct {
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.
//
// Parameters:
// - 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.
// - processor - the group chat message processor.
func LoadOrNewGroupChat(e2eID, groupID int, 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
}
func LoadOrNewGroupChat(e2eID int,
requestFunc GroupRequest, processor GroupChatProcessor) (*GroupChat, error) {
// Get user from singleton
user, err := e2eTrackerSingleton.get(e2eID)
......@@ -121,12 +105,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
// Construct a wrapper for the request callback
requestCb := func(g gs.Group) {
//fixme: review this to see if should be json marshaled.
// At the moment, groupStore.DhKeyList is an unsupported
// 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})
newGroup := groupTrackerSingleton.make(g)
requestFunc.Callback(newGroup.id)
}
// Construct a group chat manager
......@@ -137,12 +117,8 @@ func LoadOrNewGroupChat(e2eID, groupID int, requestFunc GroupRequest,
}
// Construct wrapper
return groupChatTrackerSingleton.make(gcInt), nil
}
// GetID returns the groupChatTracker ID for the GroupChat object.
func (g *GroupChat) GetID() int {
return g.id
wrapper := gc.NewWrapper(gcInt)
return &GroupChat{m: wrapper}, nil
}
// 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) {
// JoinGroup allows a user to join a group when a request is received.
//
// Parameters:
// - group - a bindings-level Group object. This is received by GroupRequest.Callback.
func (g *GroupChat) JoinGroup(group Group) error {
return g.m.JoinGroup(group.g)
// - trackedGroupId - the ID to retrieve the Group object within the backend's
// tracking system.
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.
......@@ -288,26 +277,21 @@ func (g *GroupChat) GetGroups() ([]byte, error) {
return json.Marshal(groupIds)
}
// GetGroup returns the group with the group ID. If no group exists, then the
// error "failed to find group" is returned.
// GetGroup returns the Group with the tracked ID from the backend's Group tracker.
//
// Parameters:
// - groupId - the byte data representing a group ID.
// This can be pulled from a marshalled GroupReport.
// - trackedGroupId - the ID to retrieve the Group object within the backend's
// tracking system.
// Returns:
// - Group - the bindings-layer representation of a Group.
func (g *GroupChat) GetGroup(groupId []byte) (*Group, error) {
groupID, err := id.Unmarshal(groupId)
// - Group - the bindings-layer representation of a group.
func (g *GroupChat) GetGroup(trackedGroupId int) (*Group, error) {
// Retrieve group from singleton
group, err := groupTrackerSingleton.get(trackedGroupId)
if err != nil {
return nil, errors.Errorf("Failed to unmarshal group ID: %+v", err)
}
grp, exists := g.m.GetGroup(groupID)
if !exists {
return nil, errors.New("failed to find group")
return nil, err
}
return &Group{g: grp}, nil
return group, nil
}
// NumGroups returns the number of groups the user is a part of.
......@@ -323,6 +307,7 @@ func (g *GroupChat) NumGroups() int {
// group chat.
type Group struct {
g gs.Group
id int
}
// GetName returns the name set by the user for the group.
......@@ -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.
type GroupChatProcessor interface {
Process(decryptedMessage, msg, receptionId []byte, ephemeralId,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment