Skip to content

Commit 4eddf57

Browse files
committed
fix: remove trigger
1 parent b6583d2 commit 4eddf57

File tree

3 files changed

+57
-94
lines changed

3 files changed

+57
-94
lines changed

backend/src/database/migrations/V1753110221__create_insights_repo_table.sql

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -11,97 +11,3 @@ CREATE TABLE IF NOT EXISTS "insightsProjectsRepositories" (
1111
CREATE UNIQUE INDEX IF NOT EXISTS unique_active_insights_project_repo
1212
ON "insightsProjectsRepositories" (repository)
1313
WHERE "deletedAt" IS NULL;
14-
15-
-- 3. Create or replace the sync function
16-
CREATE OR REPLACE FUNCTION sync_repositories()
17-
RETURNS TRIGGER AS $function$
18-
DECLARE
19-
repo TEXT;
20-
i INT;
21-
project_id UUID := COALESCE(NEW.id, OLD.id);
22-
BEGIN
23-
RAISE WARNING 'Trigger fired with operation: %, project ID: %', TG_OP, project_id;
24-
25-
-- DELETE: soft-delete all repositories when a project is deleted
26-
IF TG_OP = 'DELETE' THEN
27-
RAISE WARNING 'Soft-deleting all repositories for deleted project %', project_id;
28-
29-
UPDATE "insightsProjectsRepositories"
30-
SET "deletedAt" = CURRENT_TIMESTAMP
31-
WHERE "insightsProjectId" = project_id AND "deletedAt" IS NULL;
32-
33-
RETURN OLD;
34-
END IF;
35-
36-
-- INSERT or UPDATE: shared logic
37-
IF TG_OP IN ('INSERT', 'UPDATE') THEN
38-
-- On UPDATE, skip if repositories did not change
39-
IF TG_OP = 'UPDATE' AND OLD.repositories IS NOT DISTINCT FROM NEW.repositories THEN
40-
RAISE WARNING 'Repositories unchanged for project %, skipping update logic', project_id;
41-
RETURN NEW;
42-
END IF;
43-
44-
-- On UPDATE: soft-delete only removed repositories
45-
IF TG_OP = 'UPDATE' THEN
46-
RAISE WARNING 'Soft-deleting removed repositories for project %', project_id;
47-
48-
UPDATE "insightsProjectsRepositories"
49-
SET "deletedAt" = CURRENT_TIMESTAMP
50-
WHERE "insightsProjectId" = project_id
51-
AND "deletedAt" IS NULL
52-
AND repository NOT IN (SELECT unnest(NEW.repositories));
53-
END IF;
54-
55-
-- If no repositories provided, exit
56-
IF NEW.repositories IS NULL THEN
57-
RAISE WARNING 'No repositories to insert for project %', project_id;
58-
RETURN NEW;
59-
END IF;
60-
61-
RAISE WARNING 'Processing repositories for project %', project_id;
62-
63-
-- Loop through repositories and insert or revive
64-
FOR i IN COALESCE(array_lower(NEW.repositories, 1), 1)..COALESCE(array_upper(NEW.repositories, 1), 0)
65-
LOOP
66-
repo := NEW.repositories[i];
67-
RAISE WARNING 'Ensuring repository "%", project ID: %', repo, project_id;
68-
69-
-- Check if this repo is already assigned to another active project
70-
PERFORM 1 FROM "insightsProjectsRepositories"
71-
WHERE repository = repo
72-
AND "insightsProjectId" != project_id
73-
AND "deletedAt" IS NULL;
74-
75-
IF FOUND THEN
76-
RAISE EXCEPTION 'Repository "%" is already assigned to another project.', repo;
77-
END IF;
78-
79-
-- Try to revive a previously soft-deleted record
80-
UPDATE "insightsProjectsRepositories"
81-
SET "deletedAt" = NULL, "createdAt" = CURRENT_TIMESTAMP
82-
WHERE repository = repo
83-
AND "insightsProjectId" = project_id
84-
AND "deletedAt" IS NOT NULL;
85-
86-
-- If not found, insert new
87-
IF NOT FOUND THEN
88-
INSERT INTO "insightsProjectsRepositories" (repository, "insightsProjectId")
89-
VALUES (repo, project_id)
90-
ON CONFLICT DO NOTHING;
91-
END IF;
92-
END LOOP;
93-
94-
RETURN NEW;
95-
END IF;
96-
97-
RETURN NULL;
98-
END;
99-
$function$ LANGUAGE plpgsql;
100-
101-
-- 4. Create the trigger to call the function on INSERT, UPDATE, DELETE
102-
DROP TRIGGER IF EXISTS trg_insights_projects_repositories_sync ON "insightsProjects";
103-
104-
CREATE TRIGGER trg_insights_projects_repositories_sync
105-
AFTER INSERT OR DELETE OR UPDATE ON "insightsProjects"
106-
FOR EACH ROW
107-
EXECUTE FUNCTION sync_repositories();

backend/src/services/collectionService.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ import {
2020
queryCollections,
2121
queryInsightsProjectById,
2222
queryInsightsProjects,
23+
softDeleteInsightsProjectRepositories,
2324
updateCollection,
2425
updateInsightsProject,
26+
upsertInsightsProjectRepositories,
2527
} from '@crowd/data-access-layer/src/collections'
2628
import { fetchIntegrationsForSegment } from '@crowd/data-access-layer/src/integrations'
2729
import { OrganizationField, findOrgById, queryOrgs } from '@crowd/data-access-layer/src/orgs'
@@ -362,6 +364,19 @@ export class CollectionService extends LoggerBase {
362364
offset,
363365
}
364366
}
367+
368+
static normalizeRepositories(
369+
repositories?: string[] | { platform: string; url: string }[]
370+
): string[] {
371+
if (!repositories) return [];
372+
373+
if (typeof repositories[0] === 'string') {
374+
return repositories as string[];
375+
}
376+
377+
return (repositories as { platform: string; url: string }[]).map(r => r.url);
378+
}
379+
365380

366381
async updateInsightsProject(id: string, project: Partial<ICreateInsightsProject>) {
367382
return SequelizeRepository.withTx(this.options, async (tx) => {
@@ -375,6 +390,18 @@ export class CollectionService extends LoggerBase {
375390

376391
await updateInsightsProject(qx, id, project)
377392

393+
console.log(`repositories: ${project.repositories} and id: ${id}`)
394+
395+
if (project.repositories?.length > 0) {
396+
// TODO: sistemare tutto in modo che le repository possono essere anche zero
397+
const repositories = CollectionService.normalizeRepositories(project.repositories)
398+
399+
await upsertInsightsProjectRepositories(qx, `${id}`, repositories)
400+
401+
await softDeleteInsightsProjectRepositories(qx, id, repositories)
402+
}
403+
404+
378405
if (project.collections) {
379406
await disconnectProjectsAndCollections(qx, { insightsProjectId: id })
380407
await connectProjectsAndCollections(

services/libs/data-access-layer/src/collections/index.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,33 @@ export async function findBySlug(qx: QueryExecutor, slug: string) {
294294
})
295295
return collections
296296
}
297+
298+
export async function upsertInsightsProjectRepositories(qx: QueryExecutor, insightsProjectId, repositories: string[]) {
299+
const data = repositories.map((repo) => ({
300+
insightsProjectId,
301+
repository: repo,
302+
}))
303+
304+
return qx.result(
305+
prepareBulkInsert(
306+
'insightsProjectsRepositories',
307+
['insightsProjectId', 'repository'],
308+
data,
309+
'do nothing',
310+
),
311+
)
312+
}
313+
314+
export async function softDeleteInsightsProjectRepositories(
315+
qx: QueryExecutor,
316+
insightsProjectId: string,
317+
currentRepositories: string[],
318+
): Promise<void> {
319+
return qx.result(`
320+
UPDATE "insightsProjectsRepositories"
321+
SET "deletedAt" = NOW()
322+
WHERE "insightsProjectId" = '${insightsProjectId}'
323+
AND "deletedAt" IS NULL
324+
AND "repository" NOT IN (${currentRepositories.map(repo => `'${repo}'`).join(', ')})
325+
`, { insightsProjectId, currentRepositories } )
326+
}

0 commit comments

Comments
 (0)