first commit
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import {
|
||||
UpsertMaterializedActivityRepository,
|
||||
UpsertMaterializedCommentRepository,
|
||||
UpsertMaterializedIssueRepository,
|
||||
UpsertMaterializedProjectRepository,
|
||||
UpsertMaterializedReleaseRepository,
|
||||
} from '@task-stream/api/tracker/application';
|
||||
import {
|
||||
ActivityReadModel,
|
||||
CommentReadModel,
|
||||
IssueLinkReadModel,
|
||||
IssueReadModel,
|
||||
ProjectReadModel,
|
||||
ReleaseReadModel,
|
||||
} from '@task-stream/api/tracker/domain';
|
||||
import { Model } from 'mongoose';
|
||||
import {
|
||||
ActivityDoc,
|
||||
CommentDoc,
|
||||
IssueDoc,
|
||||
ProjectDoc,
|
||||
ReadModels,
|
||||
ReleaseDoc,
|
||||
} from './read-model.schemas';
|
||||
import { upsertIfNewer } from './upsert-if-newer';
|
||||
|
||||
/* Materialized views written by the event handlers (MongoDB). */
|
||||
|
||||
@Injectable()
|
||||
export class MongoUpsertMaterializedProjectRepository extends UpsertMaterializedProjectRepository {
|
||||
constructor(
|
||||
@InjectModel(ReadModels.Project)
|
||||
private readonly projects: Model<ProjectDoc>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async upsert({
|
||||
id,
|
||||
version,
|
||||
...fields
|
||||
}: Pick<ProjectReadModel, 'id' | 'version'> & Partial<ProjectReadModel>) {
|
||||
const memberIds = fields.members
|
||||
? { memberIds: fields.members.map((m) => m.user.id) }
|
||||
: {};
|
||||
await upsertIfNewer(this.projects, id, version, {
|
||||
...fields,
|
||||
...memberIds,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class MongoUpsertMaterializedIssueRepository extends UpsertMaterializedIssueRepository {
|
||||
constructor(
|
||||
@InjectModel(ReadModels.Issue) private readonly issues: Model<IssueDoc>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async upsert({
|
||||
id,
|
||||
version,
|
||||
...fields
|
||||
}: Pick<IssueReadModel, 'id' | 'version'> &
|
||||
Partial<Omit<IssueReadModel, 'links' | 'commentCount'>>) {
|
||||
await upsertIfNewer(this.issues, id, version, fields, {
|
||||
outwardLinks: [],
|
||||
inwardLinks: [],
|
||||
commentCount: 0,
|
||||
});
|
||||
}
|
||||
|
||||
async addLink(issueId: string, link: IssueLinkReadModel) {
|
||||
const field = link.direction === 'OUTWARD' ? 'outwardLinks' : 'inwardLinks';
|
||||
await this.issues.updateOne(
|
||||
{
|
||||
_id: issueId,
|
||||
[field]: {
|
||||
$not: { $elemMatch: { type: link.type, issueId: link.issueId } },
|
||||
},
|
||||
},
|
||||
{ $push: { [field]: link } },
|
||||
);
|
||||
}
|
||||
|
||||
async removeLink(
|
||||
issueId: string,
|
||||
link: Omit<IssueLinkReadModel, 'issueKey'>,
|
||||
) {
|
||||
const field = link.direction === 'OUTWARD' ? 'outwardLinks' : 'inwardLinks';
|
||||
await this.issues.updateOne(
|
||||
{ _id: issueId },
|
||||
{ $pull: { [field]: { type: link.type, issueId: link.issueId } } },
|
||||
);
|
||||
}
|
||||
|
||||
async setCommentCount(issueId: string, commentCount: number) {
|
||||
await this.issues.updateOne({ _id: issueId }, { $set: { commentCount } });
|
||||
}
|
||||
|
||||
async renameRelease(releaseId: string, name: string) {
|
||||
await this.issues.updateMany(
|
||||
{ 'release.id': releaseId },
|
||||
{ $set: { 'release.name': name } },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class MongoUpsertMaterializedCommentRepository extends UpsertMaterializedCommentRepository {
|
||||
constructor(
|
||||
@InjectModel(ReadModels.Comment)
|
||||
private readonly comments: Model<CommentDoc>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async upsert({
|
||||
id,
|
||||
version,
|
||||
...fields
|
||||
}: Pick<CommentReadModel, 'id' | 'version'> & Partial<CommentReadModel>) {
|
||||
await upsertIfNewer(this.comments, id, version, fields);
|
||||
}
|
||||
|
||||
async remove(id: string) {
|
||||
await this.comments.deleteOne({ _id: id });
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class MongoUpsertMaterializedReleaseRepository extends UpsertMaterializedReleaseRepository {
|
||||
constructor(
|
||||
@InjectModel(ReadModels.Release)
|
||||
private readonly releases: Model<ReleaseDoc>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async upsert({
|
||||
id,
|
||||
version,
|
||||
...fields
|
||||
}: Pick<ReleaseReadModel, 'id' | 'version'> & Partial<ReleaseReadModel>) {
|
||||
await upsertIfNewer(this.releases, id, version, fields);
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class MongoUpsertMaterializedActivityRepository extends UpsertMaterializedActivityRepository {
|
||||
constructor(
|
||||
@InjectModel(ReadModels.Activity)
|
||||
private readonly activity: Model<ActivityDoc>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async insert({ id, ...fields }: ActivityReadModel): Promise<boolean> {
|
||||
const result = await this.activity.updateOne(
|
||||
{ _id: id },
|
||||
{ $setOnInsert: fields },
|
||||
{ upsert: true },
|
||||
);
|
||||
return result.upsertedCount > 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user