Skip to content

Commit

Permalink
fix n+1 problem for zoom account availability (coding-blocks#82)
Browse files Browse the repository at this point in the history
* fix n+1 problem for zoom account availability

* spead options and reduce statements

* replace findOne with findAll

* reduce one loop

* don't remove some functions

* fix conflicts

* use findAll and loaderBaseClass

* remove redundant code and excludeTopic-->excludeEvent

* fix function name
  • Loading branch information
prabalsingh24 authored Jun 9, 2020
1 parent 0d8dc66 commit f923413
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 15 deletions.
15 changes: 7 additions & 8 deletions api/graphql/query/Resource/availability.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@ class ZoomAccountAvailability extends BaseResolver {
});
const topic = await resource.getTopic();

if (this.parent.subject_type === 'ZoomAccount')
return ZoomAccount.findAvailaibilityDuring(
this.parent.subject_id,
{
if (this.parent.subject_type === 'ZoomAccount') {
return await this.ctx.loaders.zoomAccountAvailability.load({
id: this.parent.id,
dateTimeRange: {
start_at: topic.start_at,
end_at: topic.end_at,
},
{
excludeTopics: [topic.id],
},
);
excludeEvents: [topic.id],
});
}

//NOTE(naman) For a new resource add finding availability logic here
return false;
Expand Down
11 changes: 5 additions & 6 deletions api/graphql/query/ZoomAccount/availability.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import ZoomAccount from 'Services/ZoomAccount';
import BaseResolver from 'Graphql/base/Resolver';

class ZoomAccountAvailability extends BaseResolver {
resolve = () =>
ZoomAccount.findAvailaibilityDuring(
this.parent.id,
this.args.dateTimeRange,
);
resolve = async () =>
await this.ctx.loaders.zoomAccountAvailability.load({
id: this.parent.id,
dateTimeRange: this.args.dateTimeRange,
});
}

export default ZoomAccountAvailability.resolver();
2 changes: 2 additions & 0 deletions api/routes/graphql/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ApolloServer } from 'apollo-server-micro';
import authenticate from 'Middlewares/authenticate';
import CalendarEventInvite from 'Services/CalendarEventInvite';
import User from 'Services/User';
import ZoomAccount from 'Services/ZoomAccount';

const server = new ApolloServer({
schema,
Expand All @@ -13,6 +14,7 @@ const server = new ApolloServer({
loaders: {
userAvailability: User.getAvailabilityLoader(),
eventInviteStatus: CalendarEventInvite.getStatusLoader(),
zoomAccountAvailability: ZoomAccount.getAvailabilityLoader()
},
}),
});
Expand Down
64 changes: 64 additions & 0 deletions api/services/ZoomAccount/Loaders/Availability.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Models from 'Models';
import BaseLoader from 'Services/BaseModelService/Loader';
import overlapDateTimeClause from 'Utils/overlapDateTimeClause';

export default class Availability extends BaseLoader {
load = async () => {
const accounts = await Models.ZoomAccount.findAll({
include: [
{
model: Models.Resource,
as: 'uses',
include: [
{
model: Models.CalendarEvent,
as: 'calendarEvent',
where: {
[Models.Sequelize.Op.or]: this.keys.map(
({ id, dateTimeRange, excludeEvents = [] }) => ({
[Models.Sequelize.Op.and]: [
overlapDateTimeClause(dateTimeRange),
{
'$zoom_account.id$': id,
},
{
id: {
[Models.Sequelize.Op.notIn]: excludeEvents,
},
},
],
}),
),
},
required: true,
},
],
required: true,
},
],
});

return this.keys.map(
(key) =>
!accounts.find((account) => this.equateKeyAndAccount(key, account)),
);
};

equateKeyAndAccount({ id, excludedEvents = [], dateTimeRange }, account) {
if (
account.id !== id ||
excludedEvents.includes(account['uses.calendarEvent.id'])
)
return false;

if (
new Date(account['uses.calendarEvent.start_at']) >
new Date(dateTimeRange.end_at) ||
new Date(account['uses.calendarEvent.end_at']) <
new Date(dateTimeRange.start_at)
)
return false;

return true;
}
}
4 changes: 3 additions & 1 deletion api/services/ZoomAccount/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import BaseModelService, {
requireInstance,
} from 'Services/BaseModelService';
import { utilizedResourceClause } from './utils';
import Availability from './Loaders/Availability';

export default class ZoomAccount extends BaseModelService {
static findAllInUse(...args) {
Expand All @@ -15,10 +16,11 @@ export default class ZoomAccount extends BaseModelService {
where: { id },
...utilizedResourceClause(...args),
});

return !data;
}

static getAvailabilityLoader = Availability.loader();

@requireInstance
ifAvailableDuring(dateTimeRange, options) {
return ZoomAccount.findAvailaibilityDuring(
Expand Down

0 comments on commit f923413

Please sign in to comment.