Skip to content

Commit

Permalink
feat: update workflow considering the potential deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
Silver-IT committed Mar 14, 2024
1 parent 3fe19d4 commit 195c033
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 22 deletions.
55 changes: 55 additions & 0 deletions frontend/controller/actions/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,61 @@ export default (sbp('sbp/selectors/register', {
sbp('okTurtles.events/emit', OPEN_MODAL, 'AddMembers')
}
},
'gi.actions/group/removeUselessIdentityContracts': function ({ contractID, possiblyUselessContractIDs }) {
// NOTE: should remove the identity contracts which we don't need to sync anymore
// for users who don't have any common groups, and any common DMs
const interval = setInterval(() => {
const pending = Object.entries(sbp('okTurtles.eventQueue/queuedInvocations'))
.filter(([q]) => typeof q === 'string')
.flatMap(([, list]) => list)

if (pending.length === 0) {
const rootState = sbp('state/vuex/state')
const rootGetters = sbp('state/vuex/getters')

const identityContractsMapToKeepSyncing = {}
const anotherGroupIDs = Object.keys(rootState.contracts)
.filter(gID => rootState.contracts[gID].type === 'gi.contracts/group' && gID !== contractID)
anotherGroupIDs.forEach(gID => {
for (const [iID] of Object.entries((rootState[gID].profiles || {}))) {
identityContractsMapToKeepSyncing[iID] = true
}
})
// NOTE: we can not use 'directMessagesByGroup' getter since
// the group contract whose ID is contractID could be already removed
const groupDirectMessages = {}
for (const chatRoomId of Object.keys(rootGetters.ourDirectMessages)) {
const chatRoomState = rootState[chatRoomId]

// NOTE: skip DMs whose chatroom contracts are not synced yet
if (!chatRoomState || !chatRoomState.members?.[rootGetters.ourIdentityContractId]) {
continue
}
// NOTE: direct messages should be filtered to the ones which are visible and of active group members
const members = Object.keys(chatRoomState.members)
const partners = members.filter(memberID => memberID !== rootGetters.ourIdentityContractId)
const hasActiveMember = partners.some(memberID => possiblyUselessContractIDs.includes(memberID))

if (hasActiveMember) {
groupDirectMessages[chatRoomId] = { partners }
}
}

for (const cID of Object.keys(groupDirectMessages)) {
groupDirectMessages[cID].partners.forEach(iID => {
identityContractsMapToKeepSyncing[iID] = true
})
}

const identityContractsToRemove = possiblyUselessContractIDs.filter(cID => !identityContractsMapToKeepSyncing[cID])
sbp('chelonia/contract/remove', identityContractsToRemove).catch(e => {
console.error(`[gi.actions/group/removeUselessIdentityContracts]: ${e.name} thrown by /remove useless identity contracts:`, e)
})

clearInterval(interval)
}
}, 1000)
},
...encryptedAction('gi.actions/group/leaveChatRoom', L('Failed to leave chat channel.')),
...encryptedAction('gi.actions/group/deleteChatRoom', L('Failed to delete chat channel.')),
...encryptedAction('gi.actions/group/invite', L('Failed to create invite.')),
Expand Down
2 changes: 1 addition & 1 deletion frontend/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async function startApp () {
'chelonia/contract/successfulKeySharesByContractID',
'gi.actions/chatroom/leave',
'gi.actions/group/removeOurselves', 'gi.actions/group/groupProfileUpdate', 'gi.actions/group/displayMincomeChangedPrompt', 'gi.actions/group/addChatRoom',
'gi.actions/group/join', 'gi.actions/group/joinChatRoom',
'gi.actions/group/join', 'gi.actions/group/joinChatRoom', 'gi.actions/group/removeUselessIdentityContracts',
'gi.actions/identity/addJoinDirectMessageKey', 'gi.actions/identity/leaveGroup',
'gi.notifications/emit',
'gi.actions/out/rotateKeys', 'gi.actions/group/shareNewKeys', 'gi.actions/chatroom/shareNewKeys', 'gi.actions/identity/shareNewPEK',
Expand Down
25 changes: 4 additions & 21 deletions frontend/model/contracts/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -1894,27 +1894,10 @@ sbp('chelonia/defineContract', {
})

if (memberID === identityContractID) {
// NOTE: should remove the identity contracts which we don't need to sync anymore
// for users who don't have any common groups, and any common DMs
const anotherGroupIDs = Object.keys(rootState.contracts)
.filter(gID => rootState.contracts[gID].type === 'gi.contracts/group' && gID !== contractID)
const identityContractsMapToKeepSyncing = {}
anotherGroupIDs.forEach(gID => {
for (const [iID] of Object.entries((rootState[gID].profiles || {}))) {
identityContractsMapToKeepSyncing[iID] = true
}
})
const groupDirectMessages = rootGetters.directMessagesByGroup(contractID)
for (const cID of Object.keys(groupDirectMessages)) {
groupDirectMessages[cID].partners.forEach(iID => {
identityContractsMapToKeepSyncing[iID] = true
})
}

const identityContractsToRemove = Object.keys(state.profiles || {})
.filter(cID => cID !== identityContractID && !identityContractsMapToKeepSyncing[cID])
sbp('chelonia/contract/remove', identityContractsToRemove).catch(e => {
console.error(`sideEffect(removeMember): ${e.name} thrown by /remove useless identity contracts:`, e)
const possiblyUselessContractIDs = Object.keys(state.profiles || {}).filter(cID => cID !== identityContractID)
sbp('gi.actions/group/removeUselessIdentityContracts', {
contractID,
possiblyUselessContractIDs
})

// we can't await on this in here, because it will cause a deadlock, since Chelonia processes
Expand Down

0 comments on commit 195c033

Please sign in to comment.