Skip to content

Commit

Permalink
feat: add db schema and logic for community entry aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
shadrach-tayo committed Jan 9, 2025
1 parent 26cd763 commit 540bf90
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 10 deletions.
1 change: 1 addition & 0 deletions desci-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"script:seed-community-member": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/seed-community-members.ts",
"script:backfill-annotations": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/backfill-annotations.ts",
"script:prune-auth-tokens": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/prune-auth-tokens.ts",
"script:backfill-radar": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/backfill-radar.ts",
"build": "rimraf dist && tsc && yarn copy-files; if [ \"$SENTRY_AUTH_TOKEN\" ]; then yarn sentry:sourcemaps; else echo 'SENTRY_AUTH_TOKEN not set, sourcemaps will not upload'; fi",
"build:worker": "cd ../sync-server && ./scripts/build.sh test",
"copy-files": "copyfiles -u 1 src/**/*.cjs dist/",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- AlterTable
ALTER TABLE "NodeAttestation" ADD COLUMN "communityRadarEntryId" INTEGER;

-- CreateTable
CREATE TABLE "CommunityRadarEntry" (
"id" SERIAL NOT NULL,
"desciCommunityId" INTEGER NOT NULL,
"nodeUuid" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "CommunityRadarEntry_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "CommunityRadarEntry_nodeUuid_desciCommunityId_key" ON "CommunityRadarEntry"("nodeUuid", "desciCommunityId");

-- AddForeignKey
ALTER TABLE "NodeAttestation" ADD CONSTRAINT "NodeAttestation_communityRadarEntryId_fkey" FOREIGN KEY ("communityRadarEntryId") REFERENCES "CommunityRadarEntry"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "CommunityRadarEntry" ADD CONSTRAINT "CommunityRadarEntry_desciCommunityId_fkey" FOREIGN KEY ("desciCommunityId") REFERENCES "DesciCommunity"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "CommunityRadarEntry" ADD CONSTRAINT "CommunityRadarEntry_nodeUuid_fkey" FOREIGN KEY ("nodeUuid") REFERENCES "Node"("uuid") ON DELETE RESTRICT ON UPDATE CASCADE;
4 changes: 2 additions & 2 deletions desci-server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -801,8 +801,8 @@ model NodeAttestation {
NodeAttestationVerification NodeAttestationVerification[]
NodeAttestationReaction NodeAttestationReaction[]
OrcidPutCodes OrcidPutCodes[]
CommunityRadarEntry CommunityRadarEntry? @relation(fields: [nodeUuid, desciCommunityId], references: [nodeUuid, desciCommunityId])
// communityRadarEntryId Int?
CommunityRadarEntry CommunityRadarEntry? @relation(fields: [communityRadarEntryId], references: [id])
communityRadarEntryId Int?
@@unique([nodeUuid, nodeVersion, attestationId, attestationVersionId])
}
Expand Down
8 changes: 8 additions & 0 deletions desci-server/src/controllers/attestations/claims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { logger } from '../../logger.js';
import { RequestWithUser } from '../../middleware/authorisation.js';
import { removeClaimSchema } from '../../routes/v1/attestations/schema.js';
import { attestationService } from '../../services/Attestation.js';
import { communityService } from '../../services/Communities.js';
import { saveInteraction } from '../../services/interactionLog.js';
import { getIndexedResearchObjects } from '../../theGraph.js';
import { asyncMap, ensureUuidEndsWithDot } from '../../utils.js';
Expand Down Expand Up @@ -38,6 +39,8 @@ export const claimAttestation = async (req: RequestWithUser, res: Response, _nex
if (claim && claim.revoked) {
const reclaimed = await attestationService.reClaimAttestation(claim.id);
await saveInteraction(req, ActionType.CLAIM_ATTESTATION, { ...body, claimId: reclaimed.id });
// trigger update radar entry
await communityService.addToRadar(reclaimed.desciCommunityId, reclaimed.nodeUuid);
new SuccessResponse(reclaimed).send(res);
return;
}
Expand All @@ -48,6 +51,8 @@ export const claimAttestation = async (req: RequestWithUser, res: Response, _nex
nodeUuid: uuid,
attestationVersion: attestationVersion.id,
});
// trigger update radar entry
await communityService.addToRadar(nodeClaim.desciCommunityId, nodeClaim.nodeUuid);

await saveInteraction(req, ActionType.CLAIM_ATTESTATION, { ...body, claimId: nodeClaim.id });

Expand Down Expand Up @@ -128,6 +133,9 @@ export const removeClaim = async (req: RequestWithUser, res: Response, _next: Ne
? await attestationService.revokeAttestation(claim.id)
: await attestationService.unClaimAttestation(claim.id);

// trigger update radar entry
await communityService.addToRadar(claim.desciCommunityId, claim.nodeUuid);

await saveInteraction(req, ActionType.REVOKE_CLAIM, body);

logger.info({ removeOrRevoke, totalSignal, claimSignal }, 'Claim Removed|Revoked');
Expand Down
29 changes: 29 additions & 0 deletions desci-server/src/controllers/communities/radar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,32 @@ export const getCommunityRadar = async (req: Request, res: Response, next: NextF

return new SuccessResponse(data).send(res);
};

export const listCommunityRadar = async (req: Request, res: Response, next: NextFunction) => {
const communityRadar = await communityService.listCommunityRadar({
communityId: parseInt(req.params.communityId as string),
offset: 0,
limit: 20,
});
logger.info({ communityRadar }, 'Radar');
// THIS is necessary because the engagement signal returned from getCommunityRadar
// accounts for only engagements on community selected attestations
const nodes = await asyncMap(communityRadar, async (entry) => {
const engagements = await attestationService.getNodeEngagementSignalsByUuid(entry.nodeUuid);
return {
...entry,
engagements,
verifiedEngagements: {
reactions: entry.reactions,
annotations: entry.annotations,
verifications: entry.verifications,
},
};
});

// rank nodes by sum of sum of verified and non verified signals

logger.info({ nodes }, 'CHECK Verification SignalS');

return new SuccessResponse(nodes).send(res);
};
25 changes: 20 additions & 5 deletions desci-server/src/scripts/backfill-radar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { prisma } from '../client.js';
import { logger } from '../logger.js';
import { communityService } from '../services/Communities.js';
// import { communityService } from '../services/Communities.js';

const main = async () => {
const nodeAttestations = await prisma.nodeAttestation.findMany({ where: { revoked: false } });
Expand All @@ -21,12 +21,20 @@ const main = async () => {
}

// check if node has claimed all community entry attestations
const entryAttestations = await communityService.getEntryAttestations({
desciCommunityId: nodeAttestation.desciCommunityId,
const entryAttestations = await prisma.communityEntryAttestation.findMany({
orderBy: { createdAt: 'asc' },
where: { desciCommunityId: nodeAttestation.desciCommunityId },
include: {
attestation: { select: { protected: true, community: { select: { name: true } } } },
// desciCommunity: { select: { name: true } },
attestationVersion: {
select: { id: true, attestationId: true, name: true, image_url: true, description: true },
},
},
});

const claimedAttestations = await prisma.nodeAttestation.findMany({
where: { desciCommunityId: nodeAttestation.desciCommunityId, nodeUuid: nodeAttestation.nodeUuid },
where: { desciCommunityId: nodeAttestation.desciCommunityId, nodeUuid: nodeAttestation.nodeUuid, revoked: false },
});

const isEntriesClaimed = entryAttestations.every((entry) =>
Expand All @@ -49,13 +57,20 @@ const main = async () => {
}
// End check if node has claimed all community entry attestations

await prisma.communityRadarEntry.create({
const radarEntry = await prisma.communityRadarEntry.create({
data: {
desciCommunityId: nodeAttestation.desciCommunityId,
nodeUuid: nodeAttestation.nodeUuid,
},
});
radarCount++;

const claims = await prisma.$transaction(
claimedAttestations.map((claim) =>
prisma.nodeAttestation.update({ where: { id: claim.id }, data: { communityRadarEntryId: radarEntry.id } }),
),
);
logger.info({ rows: claims.length }, 'Claims Updated');
}
logger.info({ radarCount }, 'Community radar fields: ');
return radarCount;
Expand Down
32 changes: 32 additions & 0 deletions desci-server/src/services/Attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,38 @@ export class AttestationService {
);
return groupedEngagements;
}

/**
* Returns all engagement signals for a node across all claimed attestations
* This verification signal is the number returned for the verification field
* @param dpid
* @returns
*/
async getNodeEngagementSignalsByUuid(uuid: string) {
const claims = (await prisma.$queryRaw`
SELECT t1.*,
count(DISTINCT "Annotation".id)::int AS annotations,
count(DISTINCT "NodeAttestationReaction".id)::int AS reactions,
count(DISTINCT "NodeAttestationVerification".id)::int AS verifications
FROM "NodeAttestation" t1
left outer JOIN "Annotation" ON t1."id" = "Annotation"."nodeAttestationId"
left outer JOIN "NodeAttestationReaction" ON t1."id" = "NodeAttestationReaction"."nodeAttestationId"
left outer JOIN "NodeAttestationVerification" ON t1."id" = "NodeAttestationVerification"."nodeAttestationId"
WHERE t1."nodeUuid" = ${uuid} AND t1."revoked" = false
GROUP BY
t1.id
`) as CommunityRadarNode[];

const groupedEngagements = claims.reduce(
(total, claim) => ({
reactions: total.reactions + claim.reactions,
annotations: total.annotations + claim.annotations,
verifications: total.verifications + claim.verifications,
}),
{ reactions: 0, annotations: 0, verifications: 0 },
);
return groupedEngagements;
}
/**
* Returns all engagement signals for a claimed attestation
* @param claimId
Expand Down
Loading

0 comments on commit 540bf90

Please sign in to comment.