-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(92): watcher leaving a room, no room deletion #186
base: master
Are you sure you want to change the base?
Changes from 5 commits
33b29a7
386d4b8
690f2a6
cc23737
f7103c0
bd75953
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,25 @@ | ||
import { success } from '../libs/response'; | ||
import { APIGatewayProxyResult } from 'aws-lambda'; | ||
import { dynamoDB } from '../libs/dynamodb-utils'; | ||
import { IEvent, success } from '../libs/response'; | ||
import { leaveRoom, findRoomOfWatcher } from '../libs/room-operations'; | ||
import { Room } from '../../extension/src/types'; | ||
|
||
export const main = async (event: IEvent): Promise<APIGatewayProxyResult> => { | ||
const watcherId: string = event.requestContext.connectionId; | ||
|
||
const room: Room = await findRoomOfWatcher( | ||
process.env.ROOM_TABLE!, | ||
watcherId, | ||
dynamoDB, | ||
); | ||
|
||
await leaveRoom(room, process.env.ROOM_TABLE!, watcherId, dynamoDB); | ||
|
||
console.log( | ||
`[WS-S] User ${watcherId} successfully deconnected from room ${room.roomId}`, | ||
); | ||
|
||
// TODO log the deletion of the room if there is no watcher | ||
|
||
export const main = async () => { | ||
return success(); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/* eslint-disable max-lines */ | ||
import { DocumentClient } from 'aws-sdk/clients/dynamodb'; | ||
import { | ||
Room, | ||
|
@@ -8,6 +9,21 @@ import { | |
import { marshallRoom, unmarshallRoom } from './room-marshalling'; | ||
import { updateWatcher } from './watcher-operations'; | ||
|
||
export const ensureRoomJoined = ( | ||
room: Room, | ||
watcherConnectionString: string, | ||
) => { | ||
if (!room.watchers[watcherConnectionString]) { | ||
console.log( | ||
'[WS-S] A media event was received for someone ho has not joined the room. Dropping', | ||
); | ||
throw new Error( | ||
`The room was not joined by watcher ${watcherConnectionString}`, | ||
); | ||
} | ||
return room; | ||
}; | ||
|
||
/** | ||
* Find a room by ID in DDB | ||
*/ | ||
|
@@ -37,6 +53,53 @@ export const findRoomById = async ( | |
} | ||
}; | ||
|
||
export const findRoomOfWatcher = async ( | ||
tableName: string, | ||
watcherConnectionString: string, | ||
dynamoDb: DocumentClient, | ||
): Promise<Room> => { | ||
const params: DocumentClient.QueryInput = { | ||
TableName: tableName, | ||
}; | ||
try { | ||
console.debug( | ||
`Trying to find room of watcher ${watcherConnectionString}`, | ||
); | ||
const data = await dynamoDb.query(params).promise(); | ||
if (data.Items) { | ||
const roomDDB: | ||
| DocumentClient.AttributeMap | ||
| undefined = data.Items.find( | ||
(r: DocumentClient.AttributeMap) => { | ||
const watchers: DocumentClient.AttributeMap = r.watchers; | ||
return ( | ||
Object.keys(watchers).find( | ||
(watcherId) => | ||
watcherId === watcherConnectionString, | ||
) !== undefined | ||
); | ||
}, | ||
); | ||
|
||
if (!roomDDB) { | ||
console.log( | ||
`Could not find the room of watcher ${watcherConnectionString}`, | ||
); | ||
throw new Error( | ||
`Could not find the room of watcher ${watcherConnectionString}`, | ||
); | ||
} | ||
return unmarshallRoom(roomDDB); | ||
} else { | ||
console.log('There is no room in the DB'); | ||
throw new Error('There is no room in the DB'); | ||
} | ||
} catch (e) { | ||
console.error('Failed to find or unmarshall room on DDB', e); | ||
throw e; | ||
} | ||
}; | ||
|
||
/** | ||
* Create a new room in DDB | ||
*/ | ||
|
@@ -137,17 +200,43 @@ export const joinExistingRoom = async ( | |
return updateWatcher(room, tableName, newWatcher, dynamoDb); | ||
}; | ||
|
||
export const ensureRoomJoined = ( | ||
/** | ||
* Removes a watcher from a room if there are 2 or more watchers | ||
* If there is only 1 watcher, delete the room after removing the watcher | ||
*/ | ||
export const leaveRoom = async ( | ||
room: Room, | ||
tableName: string, | ||
watcherConnectionString: string, | ||
) => { | ||
if (!room.watchers[watcherConnectionString]) { | ||
dynamoDb: DocumentClient, | ||
): Promise<Room | undefined> => { | ||
ensureRoomJoined(room, watcherConnectionString); | ||
delete room.watchers[watcherConnectionString]; | ||
|
||
// TODO delete the room if there is no watcher | ||
return updateRoom(room, tableName, dynamoDb); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non pour le coup pas possible d'utiliser updateRoom pour retirer un watcher. Il nous faut obligatoirement une commande AWS DynamoDB qui supprime la clé + le sous-doc uniquement, et pas une fonction qui mette à jour toute la liste des watchers (ce qui est le cas d'updateRoom ajd je crois). EDIT : non en réalité justement pour cette raison, la méthode updateRoom ne met pas à jour la liste des watchers, donc ce code ne marchera tt simplement pas SInon, ça va péter car on aura des pb de race condition avec les autres watchers. |
||
}; | ||
|
||
export const findAndEnsureRoomJoined = async ( | ||
roomId: string, | ||
watcherConnectionString: string, | ||
dynamoDB: DocumentClient, | ||
): Promise<Room> => { | ||
if (!process.env.ROOM_TABLE) { | ||
throw new Error('env.ROOM_TABLE must be defined'); | ||
} | ||
|
||
if (!roomId) { | ||
console.log( | ||
'[WS-S] A media event was received for someone ho has not joined the room. Dropping', | ||
); | ||
throw new Error( | ||
`The room was not joined by watcher ${watcherConnectionString}`, | ||
'[WS-S] Could not find an existing roomId in the join room request', | ||
); | ||
throw new Error('A room ID must be provided'); | ||
} | ||
const room = await findRoomById(roomId, process.env.ROOM_TABLE, dynamoDB); | ||
if (!room) { | ||
console.log('[WS-S] Could not find room ', roomId); | ||
throw new Error('Room ${roomId} does not exist and cannot be joined'); | ||
} | ||
ensureRoomJoined(room, watcherConnectionString); | ||
return room; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.