Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
95dc24f
First attempt to improve segment activity channels
loicsaintroch Aug 25, 2023
a7530ba
Merge remote-tracking branch 'origin/main' into improvement/activityc…
loicsaintroch Aug 25, 2023
9a47210
Merge remote-tracking branch 'origin/main' into improvement/activityc…
loicsaintroch Aug 28, 2023
f94b2a9
Make linter happier
loicsaintroch Aug 28, 2023
005e606
Make linter happy
loicsaintroch Aug 28, 2023
cad3ea8
Make linter happy
loicsaintroch Aug 28, 2023
9ff1828
Make formatter happy
loicsaintroch Aug 28, 2023
a3b282b
Merge remote-tracking branch 'origin/main' into feature/c-2161-optimi…
loicsaintroch Aug 28, 2023
5f1ac81
Merge remote-tracking branch 'origin/main' into feature/c-2161-optimi…
loicsaintroch Aug 29, 2023
6efd392
Improve business logic
loicsaintroch Aug 29, 2023
a817556
Make formatter happy
loicsaintroch Aug 29, 2023
1f8e541
Merge remote-tracking branch 'origin/main' into feature/c-2161-optimi…
loicsaintroch Aug 29, 2023
1f255a8
Fix select and upsert segments
loicsaintroch Aug 29, 2023
beee50f
Merge remote-tracking branch 'origin/main' into feature/c-2161-optimi…
loicsaintroch Aug 29, 2023
563bc9b
Merge remote-tracking branch 'origin/main' into feature/c-2161-optimi…
loicsaintroch Aug 30, 2023
b96d7af
Improve SQL query for upsert
loicsaintroch Aug 30, 2023
03950f2
Make linter happy
loicsaintroch Aug 30, 2023
d6604a3
Merge remote-tracking branch 'origin/main' into feature/c-2161-optimi…
loicsaintroch Aug 30, 2023
3dfdc0f
Merge branch 'main' into feature/c-2161-optimize-handling-of-segments…
Sep 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS "public"."segmentActivityChannels" CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CREATE TABLE IF NOT EXISTS "public"."segmentActivityChannels" (
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
"tenantId" UUID NOT NULL REFERENCES public.tenants(id) ON UPDATE CASCADE ON DELETE CASCADE,
"segmentId" UUID NOT NULL REFERENCES public.segments(id) ON UPDATE CASCADE ON DELETE CASCADE,
"platform" TEXT NOT NULL,
"channel" TEXT NOT NULL
);

CREATE UNIQUE INDEX unique_segment_activity_channel
ON "public"."segmentActivityChannels" ("tenantId", "segmentId", "platform", "channel");

INSERT INTO "public"."segmentActivityChannels" ("segmentId", "tenantId", "platform", "channel")
SELECT
"id",
"tenantId",
jsonb_object_keys("activityChannels"),
TRIM('"' FROM jsonb_array_elements("activityChannels"->jsonb_object_keys("activityChannels"))::TEXT)
FROM "public"."segments";
187 changes: 129 additions & 58 deletions backend/src/database/repositories/segmentRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,39 +182,71 @@ class SegmentRepository extends RepositoryBase<
'sourceId',
'sourceParentId',
'customActivityTypes',
'activityChannels',
].includes(key),
)

let segmentUpdateQuery = `UPDATE segments SET `
const replacements = {} as any
if (updateFields.length > 0) {
let segmentUpdateQuery = `UPDATE segments SET `
const replacements = {} as any

for (const field of updateFields) {
segmentUpdateQuery += ` "${field}" = :${field} `
replacements[field] = data[field]
for (const field of updateFields) {
segmentUpdateQuery += ` "${field}" = :${field} `
replacements[field] = data[field]

if (updateFields[updateFields.length - 1] !== field) {
segmentUpdateQuery += ', '
if (updateFields[updateFields.length - 1] !== field) {
segmentUpdateQuery += ', '
}
}
}

segmentUpdateQuery += ` WHERE id = :id and "tenantId" = :tenantId `
replacements.tenantId = this.options.currentTenant.id
replacements.id = id
segmentUpdateQuery += ` WHERE id = :id and "tenantId" = :tenantId `
replacements.tenantId = this.options.currentTenant.id
replacements.id = id

if (replacements.customActivityTypes) {
replacements.customActivityTypes = JSON.stringify(replacements.customActivityTypes)
}
if (replacements.customActivityTypes) {
replacements.customActivityTypes = JSON.stringify(replacements.customActivityTypes)
}

if (replacements.activityChannels) {
replacements.activityChannels = JSON.stringify(replacements.activityChannels)
await this.options.database.sequelize.query(segmentUpdateQuery, {
replacements,
type: QueryTypes.UPDATE,
transaction,
})
}

await this.options.database.sequelize.query(segmentUpdateQuery, {
replacements,
type: QueryTypes.UPDATE,
transaction,
})
if (data.activityChannels && typeof data.activityChannels === 'object') {
if (Object.keys(data.activityChannels).length > 0) {
const replacements = {}
let valuePlaceholders = ''
Object.keys(data.activityChannels).forEach((platform) => {
data.activityChannels[platform].forEach((channel, i) => {
valuePlaceholders += data.activityChannels[platform]
.map(
() =>
`(:tenantId_${platform}_${i}, :segmentId_${platform}_${i}, :platform_${platform}_${i}, :channel_${platform}_${i})`,
)
.join(', ')

replacements[`tenantId_${platform}_${i}`] = this.options.currentTenant.id
replacements[`segmentId_${platform}_${i}`] = id
replacements[`platform_${platform}_${i}`] = platform
replacements[`channel_${platform}_${i}`] = channel
})
})

await this.options.database.sequelize.query(
`
INSERT INTO "segmentActivityChannels" ("tenantId", "segmentId", "platform", "channel")
VALUES ${valuePlaceholders}
ON CONFLICT DO NOTHING;
`,
{
replacements,
type: QueryTypes.INSERT,
transaction,
},
)
}
}

return this.findById(id)
}
Expand Down Expand Up @@ -298,11 +330,22 @@ class SegmentRepository extends RepositoryBase<
const transaction = this.transaction

const records = await this.options.database.sequelize.query(
`SELECT *
FROM segments
WHERE id in (:ids)
and "tenantId" = :tenantId;
`,
`SELECT
s.*,
json_agg(sac."activityChannels") AS "activityChannels"
FROM segments s
LEFT JOIN (
SELECT
"tenantId",
json_build_object(concat(platform), json_agg(sac.channel)) AS "activityChannels"
FROM "segmentActivityChannels" sac
WHERE "tenantId" = :tenantId
GROUP BY "tenantId", "platform"
) sac
ON sac."tenantId" = s."tenantId"
WHERE id in (:ids)
AND s."tenantId" = :tenantId
GROUP BY s.id;`,
{
replacements: {
ids,
Expand All @@ -313,6 +356,10 @@ class SegmentRepository extends RepositoryBase<
},
)

records.forEach((row) => {
row.activityChannels = Object.assign({}, ...row.activityChannels)
})

return records.map((sr) => SegmentRepository.populateRelations(sr))
}

Expand All @@ -333,11 +380,22 @@ class SegmentRepository extends RepositoryBase<
const transaction = this.transaction

const records = await this.options.database.sequelize.query(
`SELECT *
FROM segments
WHERE id = :id
and "tenantId" = :tenantId;
`,
`SELECT
s.*,
json_agg(sac."activityChannels") AS "activityChannels"
FROM segments s
LEFT JOIN (
SELECT
"tenantId",
json_build_object(concat(platform), json_agg(sac.channel)) AS "activityChannels"
FROM "segmentActivityChannels" sac
WHERE "tenantId" = :tenantId
GROUP BY "tenantId", "platform"
) sac
ON sac."tenantId" = s."tenantId"
WHERE s.id = :id
AND s."tenantId" = :tenantId
GROUP BY s.id;`,
{
replacements: {
id,
Expand All @@ -353,6 +411,7 @@ class SegmentRepository extends RepositoryBase<
}

const record = records[0]
record.activityChannels = Object.assign({}, ...record.activityChannels)

if (SegmentRepository.isProjectGroup(record)) {
// find projects
Expand Down Expand Up @@ -569,17 +628,27 @@ class SegmentRepository extends RepositoryBase<

const subprojects = await this.options.database.sequelize.query(
`
select s.*,
count(*) over () as "totalCount"
from segments s
where s."grandparentSlug" is not null
and s."parentSlug" is not null
and s."tenantId" = :tenantId
${searchQuery}
GROUP BY s."id"
ORDER BY s."name"
${this.getPaginationString(criteria)};
`,
SELECT
COUNT(DISTINCT s.id) AS count,
s.*,
json_agg(sac."activityChannels") AS "activityChannels"
FROM segments s
LEFT JOIN (
SELECT
"tenantId",
json_build_object(concat(platform), json_agg(sac.channel)) AS "activityChannels"
FROM "segmentActivityChannels" sac
WHERE "tenantId" = :tenantId
GROUP BY "tenantId", "platform"
) sac
ON sac."tenantId" = s."tenantId"
WHERE s."grandparentSlug" IS NOT NULL
AND s."parentSlug" IS NOT NULL
AND s."tenantId" = :tenantId
${searchQuery}
GROUP BY s.id
${this.getPaginationString(criteria)};
`,
{
replacements: {
tenantId: this.currentTenant.id,
Expand All @@ -592,15 +661,14 @@ class SegmentRepository extends RepositoryBase<
},
)

const count = subprojects.length > 0 ? Number.parseInt(subprojects[0].totalCount, 10) : 0
const count = subprojects.length > 0 ? Number.parseInt(subprojects[0].count, 10) : 0

const integrationsBySegments = await this.queryIntegrationsForSubprojects(subprojects)

const rows = subprojects.map((i) => {
let subproject = removeFieldsFromObject(i, 'totalCount')
subproject = SegmentRepository.populateRelations(subproject)
subproject.integrations = integrationsBySegments[subproject.id] || []
return subproject
const rows = subprojects
rows.forEach((row, i) => {
rows[i].activityChannels = rows[i].activityChannels[0]
if (rows[i].activityChannels === null) {
rows[i].activityChannels = {}
}
})

// TODO: Add member count to segments after implementing member relations
Expand Down Expand Up @@ -657,14 +725,17 @@ class SegmentRepository extends RepositoryBase<

static getActivityChannels(options: IRepositoryOptions) {
const channels = {}

for (const segment of options.currentSegments) {
for (const platform of Object.keys(segment.activityChannels)) {
if (!channels[platform]) {
channels[platform] = new Set<string>(segment.activityChannels[platform])
} else {
segment.activityChannels[platform].forEach((ch) =>
(channels[platform] as Set<string>).add(ch),
)
if (segment.activityChannels) {
for (const platform of Object.keys(segment.activityChannels)) {
if (!channels[platform]) {
channels[platform] = new Set<string>(segment.activityChannels[platform])
} else {
segment.activityChannels[platform].forEach((ch) =>
(channels[platform] as Set<string>).add(ch),
)
}
}
}
}
Expand Down
Loading