Skip to content

Commit

Permalink
Optimize performance by minimizing number of subscriptions and parall…
Browse files Browse the repository at this point in the history
…el fetches

Supabase realtime has an undocumented limitation that the subscription
channel name must be unique. supabase/realtime#271
It is very badly documented, but the channel name can actually be any
string. So we can fix this by using the store name for the subscription
channel.

Fixing this resulted in more distinct subscriptions, so I had to put some
effort into reducing this number back down to the minimum.
If a store is already subscribed, we don't have to subscribe again. This
was especially important for the abteilungen store, which is
re-subscribed every time the group scores change (I think because of the
group ranking).

Also, force reloading should still not cause overlapping duplicate
requests. The forceReload flag should just affect the case when there is
already data present in the store.
  • Loading branch information
carlobeltrame committed Feb 1, 2023
1 parent 728ed74 commit 770d3c5
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 20 deletions.
3 changes: 2 additions & 1 deletion src/composables/useCurrentMrT.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ export function useCurrentMrT() {
},
actions: {
subscribe() {
if (this.subscribed) return
this.subscribed = true
supabase
.channel(`public:mr_t_changes`)
.channel('currentMrT')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'mr_t_changes' },
Expand Down
20 changes: 8 additions & 12 deletions src/stores/chatContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ export const useChatContents = (groupId) => {
},
actions: {
subscribe() {
if (this.subscribed) return
this.subscribed = true

// For some reason, this only keeps the last added of each store subscribed...
//this.allStores.forEach((store) => store.subscribe())
// Instead, we manage the subscriptions of paginated slices right here.
// In order to reduce the number of subscriptions, we only subscribe once to each table
// and then delegate the callback to all our paginaged slice stores
this._subscribeAll('messages', 'messagesStores')
this._subscribeAll('station_visits', 'stationVisitsStores')
this._subscribeAll('joker_visits', 'jokerVisitsStores')
Expand All @@ -63,20 +63,16 @@ export const useChatContents = (groupId) => {
},
_subscribeAll(table, storesGetter) {
supabase
.channel('public:' + table)
.on(
'postgres_changes',
{ event: '*', schema: 'public', table },
() => {
this[storesGetter].forEach((store) => store.fetch(true))
}
.channel(`chatContent-${table}`)
.on('postgres_changes', { event: '*', schema: 'public', table }, () =>
this[storesGetter].forEach((store) => store.fetch(true))
)
.subscribe()
},
async fetch(forceReload = false) {
if (this.fetching && !forceReload) return
if (this.fetching) return
this.fetching = true
await Promise.all(
await Promise.allSettled(
this.allStores.map((store) => store.fetch(forceReload))
)
this.fetching = false
Expand Down
5 changes: 3 additions & 2 deletions src/stores/collectionStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ export const useCollectionStore = (
},
actions: {
subscribe() {
if (this.subscribed) return
this.subscribed = true
supabase
.channel('public:' + table)
.channel(storeId)
.on('postgres_changes', { event: '*', schema: 'public', table }, () =>
this.fetch(true)
)
.subscribe()
return this.fetch()
},
async fetch(forceReload = false) {
if ((this.fetching || this.data) && !forceReload) return
if (this.fetching || (this.data && !forceReload)) return
this.fetching = true
const query = supabase.from(table).select(select)
const { data } = await applyFilterToQuery(query, filter)
Expand Down
8 changes: 5 additions & 3 deletions src/stores/entryStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export const useEntryStore = (
{ initialData = undefined, select = '*' }
) => {
return (id) => {
return defineStore(`${table}-${id}-${select}`, {
const storeId = `${table}-${id}-${select}`
return defineStore(storeId, {
state: () => ({ data: initialData, subscribed: false, fetching: false }),
getters: {
loading: (state) => state.data === undefined,
Expand All @@ -16,9 +17,10 @@ export const useEntryStore = (
},
actions: {
subscribe() {
if (this.subscribed) return
this.subscribed = true
supabase
.channel(`public:${table}:id=eq.${id}`)
.channel(storeId)
.on(
'postgres_changes',
{
Expand All @@ -33,7 +35,7 @@ export const useEntryStore = (
return this.fetch()
},
async fetch(forceReload = false) {
if ((this.fetching || this.data) && !forceReload) return
if (this.fetching || (this.data && !forceReload)) return
this.fetching = true
const { data } = await supabase
.from(table)
Expand Down
3 changes: 2 additions & 1 deletion src/stores/groupScores.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { gsap } from 'gsap'
export const useGroupScores = () => {
const subscribeToTable = (table, callback) => {
supabase
.channel(`public:${table}`)
.channel(`groupScores-${table}`)
.on('postgres_changes', { event: '*', schema: 'public', table }, callback)
.subscribe()
}
Expand Down Expand Up @@ -42,6 +42,7 @@ export const useGroupScores = () => {
},
actions: {
subscribe() {
if (this.subscribed) return
this.subscribed = true
subscribeToTable('abteilungen', () => this.fetch(true))
subscribeToTable('groups', () => this.fetch(true))
Expand Down
3 changes: 2 additions & 1 deletion src/stores/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ export const useSettings = () =>
},
actions: {
subscribe() {
if (this.subscribed) return
this.subscribed = true
supabase
.channel(`public:settings`)
.channel('settings')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'settings' },
Expand Down

0 comments on commit 770d3c5

Please sign in to comment.