moved requests from Firestore to Realtime DB

optimize-reads
Simon Huang 5 years ago
parent a5d20f5d16
commit 5cdf300651

@ -21,14 +21,6 @@ const collection = {
roomId: {
createdAt: 'timestamp',
ownerId: 'userId',
requests: [
{
createdAt: 'timestamp',
data: '01:25:44', // Contents of data depend on type of request
type: 'updateState',
senderId: 'userId',
},
],
},
},
],
@ -69,6 +61,18 @@ const turtle = {
},
},
// Keeping state requests in Realtime DB could also lower cost
requests: {
roomId: {
requestId: {
createdAt: '2020-10-31T00:12:14.234Z',
data: '01:25:44', // Contents of data depend on type of request
type: 'updateState',
senderId: 'userId',
},
},
},
// Keeping track of which users are present in a room
rooms: {
roomId: {

@ -1,7 +1,7 @@
import { IonCol, IonContent, IonFabButton, IonGrid, IonIcon, IonInput, IonRow, IonToolbar } from '@ionic/react';
import { sendOutline } from 'ionicons/icons';
import React, { useEffect, useRef, useState } from 'react';
import { db, rtdb } from '../services/firebase';
import { rtdb } from '../services/firebase';
import { secondsToTimestamp } from '../services/utilities';
import './Messages.css';
@ -56,32 +56,24 @@ const Messages: React.FC<MessagesProps> = ({ pane, ownerId, roomId, userId, user
// Listen for new system messages
useEffect(() => {
const roomUnsubscribe = db
.collection('rooms')
.doc(roomId)
.onSnapshot((docSnapshot) => {
const docData = docSnapshot.data();
if (docData !== undefined) {
const requests = docData.requests;
let arr: Message[] = [];
for (const req of requests) {
if (req.createdAt > joinTime && req.type !== 'updateState') {
arr.push({
content: processType(req.type, req.data),
createdAt: req.createdAt,
id: req.senderId + req.createdAt,
senderId: req.senderId,
type: req.type,
});
}
}
setSystemMessages(arr);
}
});
let arr: Message[] = [];
rtdb.ref('/requests/' + roomId).on('child_added', (snapshot) => {
const req = snapshot.val();
if (req.createdAt > joinTime && req.type !== 'updateState') {
arr.push({
content: processType(req.type, req.data),
createdAt: req.createdAt,
id: req.senderId + req.createdAt,
senderId: req.senderId,
type: req.type,
});
let copyArr = [...arr];
setSystemMessages(copyArr);
}
});
return () => {
roomUnsubscribe();
rtdb.ref('/requests/' + roomId).off('child_added');
};
}, [roomId, joinTime]);

@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import ReactPlayer from 'react-player';
import { arrayUnion, db } from '../../services/firebase';
import { db, rtdb } from '../../services/firebase';
import { SYNC_MARGIN } from '../../services/utilities';
type ReactPlayerFrameProps = {
@ -25,11 +25,7 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
time: currTime,
});
db.collection('rooms')
.doc(roomId)
.update({
requests: arrayUnion({ createdAt: Date.now(), senderId: userId, data: currTime, type: 'play' }),
});
rtdb.ref('/requests/' + roomId).push({ createdAt: Date.now(), senderId: userId, data: currTime, type: 'play' });
}
}
};
@ -45,11 +41,9 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
time: currTime,
});
db.collection('rooms')
.doc(roomId)
.update({
requests: arrayUnion({ createdAt: Date.now(), senderId: userId, data: currTime, type: 'pause' }),
});
rtdb
.ref('/requests/' + roomId)
.push({ createdAt: Date.now(), senderId: userId, data: currTime, type: 'pause' });
}
}
};
@ -57,14 +51,12 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
// Listen for requests from Firebase (owner only)
useEffect(() => {
if (ownerId === userId) {
const roomRef = db.collection('rooms').doc(roomId);
const stateRef = db.collection('states').doc(roomId);
const requestRef = rtdb.ref('/requests/' + roomId);
// Add a listener to 'rooms' collection, listening for updateState requests
const roomUnsubscribe = roomRef.onSnapshot((docSnapshot) => {
const requests = docSnapshot.data()?.requests;
const req = requests[requests.length - 1];
requestRef.limitToLast(1).on('child_added', (snapshot) => {
const req = snapshot.val();
if (!!req && req.type === 'updateState' && req.senderId !== userId) {
const currTime = player.current?.getCurrentTime();
if (currTime !== undefined) {
@ -77,7 +69,7 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
});
return () => {
roomUnsubscribe();
requestRef.limitToLast(1).off('child_added');
};
}
}, [ownerId, roomId, userId]);
@ -85,11 +77,7 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
// Request an update after buffering is finished (member only)
const onBufferEnd = () => {
if (ownerId !== userId) {
db.collection('rooms')
.doc(roomId)
.update({
requests: arrayUnion({ createdAt: Date.now(), senderId: userId, data: 0, type: 'updateState' }),
});
rtdb.ref('/requests/' + roomId).push({ createdAt: Date.now(), senderId: userId, data: 0, type: 'updateState' });
}
};
@ -97,7 +85,7 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
useEffect(() => {
if (ownerId !== userId) {
const stateRef = db.collection('states').doc(roomId);
const roomRef = db.collection('rooms').doc(roomId);
const requestRef = rtdb.ref('/requests/' + roomId);
let allowUpdate = true;
// listen to 'states' collection for video state changes from owner
@ -118,9 +106,7 @@ const ReactPlayerFrame: React.FC<ReactPlayerFrameProps> = ({ ownerId, userId, ro
}, 5000);
player.current?.seekTo(realTimeState);
roomRef.update({
requests: arrayUnion({ createdAt: Date.now(), senderId: userId, data: 0, type: 'updateState' }),
});
requestRef.push({ createdAt: Date.now(), senderId: userId, data: 0, type: 'updateState' });
}
}
});

@ -2,7 +2,7 @@ import { IonFabButton, IonIcon, IonInput, IonTitle, IonToolbar } from '@ionic/re
import { add } from 'ionicons/icons';
import React, { useState } from 'react';
import { useHistory } from 'react-router';
import { db, arrayUnion } from '../services/firebase';
import { db, rtdb } from '../services/firebase';
import './RoomHeader.css';
type RoomHeaderProps = {
@ -21,13 +21,7 @@ const RoomHeader: React.FC<RoomHeaderProps> = ({ roomId, userId, ownerId }) => {
url: videoUrl,
});
await db
.collection('rooms')
.doc(roomId)
.update({
requests: arrayUnion({ createdAt: Date.now(), senderId: userId, data: 0, type: 'change' }),
});
await rtdb.ref('/requests/' + roomId).push({ createdAt: Date.now(), senderId: userId, data: 0, type: 'change' });
setVideoUrl('');
}
};

@ -17,7 +17,7 @@ import {
import { logoGithub } from 'ionicons/icons';
import React, { useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { arrayUnion, db, rtdb } from '../services/firebase';
import { db, rtdb } from '../services/firebase';
import './Settings.css';
type SettingsProps = {
@ -42,16 +42,9 @@ const Settings: React.FC<SettingsProps> = ({ pane, roomId, userId }) => {
rtdb.ref('/rooms/' + roomId + '/' + userId).set({ name: newName });
// Send 'nameChange' request for all clients to get a message about the name change
db.collection('rooms')
.doc(roomId)
.update({
requests: arrayUnion({
createdAt: Date.now(),
senderId: userId,
data: { prev: prevName, curr: newName },
type: 'nameChange',
}),
});
rtdb
.ref('/requests/' + roomId)
.push({ createdAt: Date.now(), senderId: userId, data: { prev: prevName, curr: newName }, type: 'nameChange' });
setShowNameChange(true);
}
@ -103,12 +96,12 @@ const Settings: React.FC<SettingsProps> = ({ pane, roomId, userId }) => {
<IonRow class="externals-row">
<IonCol size="3"></IonCol>
<IonCol size="3">
<IonRouterLink href="https://github.com/shuang854/Turtle" target="_blank">
<IonRouterLink href="https://github.com/shuang854/Turtle" target="_blank" rel="noopener noreferrer">
<IonIcon icon={logoGithub} class="about-icons"></IonIcon>
</IonRouterLink>
</IonCol>
<IonCol size="3">
<IonRouterLink href="https://discord.gg/NEw3Msu" target="_blank">
<IonRouterLink href="https://discord.gg/NEw3Msu" target="_blank" rel="noopener noreferrer">
<Icon icon={discordIcon} className="about-icons"></Icon>
</IonRouterLink>
</IonCol>

@ -52,8 +52,6 @@ const Home: React.FC = () => {
const roomId = await db.collection('rooms').add({
createdAt: timestamp,
ownerId: userId,
requests: [],
state: { time: 0, isPlaying: false },
});
await db.collection('playlists').doc(roomId.id).set({
createdAt: timestamp,
@ -112,7 +110,7 @@ const Home: React.FC = () => {
</IonRow>
<IonRow>
<IonCol class="request-col">
<a href="https://discord.gg/NEw3Msu" target="_blank">
<a href="https://discord.gg/NEw3Msu" target="_blank" rel="noopener noreferrer">
Request more options
</a>
</IonCol>

Loading…
Cancel
Save