soft delete

This commit is contained in:
Peter Maquiran
2024-08-26 14:47:03 +01:00
parent 0f94af5f4e
commit 021d1c5277
31 changed files with 125 additions and 92 deletions
+2 -2
View File
@@ -54,7 +54,7 @@ export class ChatModule {
this.typingCallback[id].next()
}
})
}
async syncMessage() {
@@ -72,7 +72,7 @@ export class ChatModule {
connection.subscribe((value: boolean) => {
if(value) {
// on connect
// this.ChatServiceService.sendLocalMessages()
this.ChatServiceService.sendLocalMessages()
}
})
@@ -7,13 +7,13 @@ import { AttachmentTable, AttachmentTableSchema } from '../../infra/database/dex
@Injectable({
providedIn: 'root'
})
export class AttachmentLocalDataSource extends DexieRepository<AttachmentTable> {
export class AttachmentLocalDataSource extends DexieRepository<AttachmentTable, AttachmentTable> {
messageSubject = new Subject();
constructor() {
super(chatDatabase.attachment, AttachmentTableSchema)
}
}
@@ -12,7 +12,7 @@ import { from } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class MemberListLocalRepository extends DexieRepository<MemberTable> {
export class MemberListLocalRepository extends DexieRepository<MemberTable, MemberTable> {
constructor() {
super(chatDatabase.members, MemberTableSchema)
@@ -35,13 +35,6 @@ export class MemberListLocalRepository extends DexieRepository<MemberTable> {
async addMember(data: MemberTable) {
data.$roomIdUserId = data.roomId + data.wxUserId
return this.insert(data)
// try {
// data.$roomIdUserId = data.roomId + data.wxUserId
// const result = await chatDatabase.members.add(data)
// return ok(result)
// } catch (e) {
// return err(false)
// }
}
async updateMemberRole(data: MemberTable) {
@@ -85,15 +78,11 @@ export class MemberListLocalRepository extends DexieRepository<MemberTable> {
async removeMemberFromRoom($roomIdUserId): Promise<Result<any ,any>> {
try {
const member = await chatDatabase.members.where({ $roomIdUserId: $roomIdUserId }).first();
if (member) {
const result = ok(await chatDatabase.members.delete($roomIdUserId));
console.log(`Member with $roomIdUserId ${$roomIdUserId} removed from room ${member.roomId}.`);
return result
} else {
console.log(`No member found with $roomIdUserId ${$roomIdUserId}`);
return err('not Found')
}
@@ -55,6 +55,11 @@ export class MessageSocketRepositoryService {
async sendGroupMessage(data: MessageInputDTO) {
if(data['requestId']) {
data['requestId'] = InstanceId +'@'+ uuidv4();
}
const result = await this.socket.sendData<MessageOutPutDataDTO>({
method: 'sendMessage',
data: data,
@@ -64,6 +69,10 @@ export class MessageSocketRepositoryService {
}
async sendDirectMessage(data: MessageInputDTO) {
if(data['requestId']) {
data['requestId'] = InstanceId +'@'+ uuidv4();
}
const result = await this.socket.sendData<MessageOutPutDataDTO>({
method: 'SendDirectMessage',
data: data as any,
@@ -3,7 +3,7 @@ import { liveQuery } from 'Dexie';
import { err, ok, Result } from 'neverthrow';
import { Observable, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { MessageEntity } from '../../../domain/entity/message';
import { MessageEntity } from '../../../../../core/chat/entity/message';
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
import { MessageTable, MessageTableSchema } from 'src/app/module/chat/infra/database/dexie/schema/message';
import { chatDatabase } from '../../../infra/database/dexie/service';
@@ -12,7 +12,7 @@ import { Observable as DexieObservable, PromiseExtended } from 'Dexie';
@Injectable({
providedIn: 'root'
})
export class MessageLocalDataSourceService extends DexieRepository<MessageTable> {
export class MessageLocalDataSourceService extends DexieRepository<MessageTable, MessageEntity> {
messageSubject = new Subject();
@@ -28,7 +28,6 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
// Perform the update operation within the transaction
await chatDatabase.message.toCollection().modify({ sending: false });
});
console.log('All messages updated successfully.');
} catch (error) {
console.error('Error updating messages:', error);
}
@@ -49,7 +48,7 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
}
}
async deleteByMessageId(id: string): Promise<Result<undefined|MessageTable, any>> {
async deleteByMessageId(id: string): Promise<Result<undefined|number, any>> {
try {
console.log(id)
const lastMessage = await chatDatabase.message
@@ -197,10 +196,6 @@ export class MessageLocalDataSourceService extends DexieRepository<MessageTable>
.filter(msg => typeof msg.id !== 'string' && msg.sending == false)
.toArray();
console.log("======================================================================")
console.log({localMessage:allMessages})
return allMessages as MessageEntity[];
} catch (error) {
console.error('Error fetching messages:', error);
@@ -12,7 +12,7 @@ import { from } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class RoomLocalRepository extends DexieRepository<RoomTable> {
export class RoomLocalRepository extends DexieRepository<RoomTable, RoomTable> {
constructor() {
super(chatDatabase.room, RoomTableSchema)
@@ -32,13 +32,13 @@ import { GetMessageAttachmentLocallyUseCaseService } from 'src/app/module/chat/d
import { GetRoomListUseCaseService } from 'src/app/module/chat/domain/use-case/room-get-list-use-case.service';
import { filter } from 'rxjs/operators';
import { v4 as uuidv4 } from 'uuid'
import { MessageEntity } from './entity/message';
import { MessageEntity } from '../../../core/chat/entity/message';
import { MessageAttachmentByMessageIdInput, MessageAttachmentByMessageIdUseCase } from './use-case/message-attachment-by-message-id.service';
import { RoomInputDTO } from '../data/dto/room/roomInputDTO';
import { UserRemoveListInputDTO } from '../data/dto/room/userRemoveListInputDTO';
import { AddMemberToRoomInputDTO } from '../data/dto/room/addMemberToRoomInputDto';
import { RoomUpdateInputDTO } from '../data/dto/room/roomUpdateInputDTO';
import { RoomType } from "src/app/module/chat/domain/entity/group";
import { RoomType } from "src/app/core/chat/entity/group";
import { sendReadAt } from "src/app/module/chat/data/repository/message/message-live-signalr-data-source.service";
export const InstanceId = uuidv4();
@@ -128,7 +128,7 @@ export class ChatServiceService {
async start() {
await this.chatSync()
this.SocketConnectUseCaseService.execute();
await this.SocketConnectUseCaseService.execute();
}
@@ -1,4 +0,0 @@
export enum RoomType {
Group = 1,
Direct = 2
}
@@ -1,99 +0,0 @@
import { z } from "zod";
import { MessageAttachmentFileType, MessageAttachmentSource } from "../../data/dto/message/messageOutputDTO";
import { SafeResourceUrl } from "@angular/platform-browser";
import { base64Schema } from "src/app/utils/zod";
export const MessageEntitySchema = z.object({
$id: z.any().optional(),
id: z.string().optional(),
roomId: z.string().uuid().optional(),
receiverId: z.number().optional(),
message: z.string().optional(),
messageType: z.number(),
canEdit: z.boolean(),
oneShot: z.boolean(),
sentAt: z.string().optional(),
requireUnlock: z.boolean(),
editedAt: z.string().nullable().optional(),
sender: z.object({
wxUserId: z.number(),
wxFullName: z.string(),
wxeMail: z.string(),
userPhoto: z.string(),
}),
info: z.array(z.object({
memberId: z.number(),
readAt: z.string().nullable(),
deliverAt: z.string().nullable()
})).optional(),
sending: z.boolean().optional(),
attachments: z.array(z.object({
fileType: z.nativeEnum(MessageAttachmentFileType),
source: z.nativeEnum(MessageAttachmentSource),
file: base64Schema.optional(),
fileName: z.string().optional(),
applicationId: z.number().optional(),
docId: z.string().optional(),
id: z.string().optional(),
mimeType: z.string().optional()
})).optional()
})
type Message = z.infer<typeof MessageEntitySchema>;
export class MessageEntity {
$id?: number
id?: string
roomId?: string
receiverId?: number
message?: string
messageType: number = 0
canEdit: boolean = false
oneShot: boolean = false
sentAt?: string
requireUnlock: boolean = false
info: {
memberId?: number
readAt?: string,
deliverAt?: string
}[] = []
sender!: {
wxUserId: number,
wxFullName: string,
wxeMail: string,
userPhoto: string,
}
sending: boolean = false
sendAttemp = 0
attachments: {
safeFile?: SafeResourceUrl;
fileType: MessageAttachmentFileType,
source: MessageAttachmentSource,
file?: string,
fileName: string,
applicationId?: number,
docId?: string,
mimeType?: string,
description?: string
id?: string
}[] = []
reactions = []
requestId!: string
constructor() {}
get messageStatus() {
if(this.id) {
return 'send'
}
}
get hasAttachment() {
return this.attachments.length >= 1
}
}
@@ -1,6 +1,6 @@
import { MessageInputDTO } from "../../data/dto/message/messageInputDtO";
import { MessageOutPutDataDTO } from "../../data/dto/message/messageOutputDTO";
import { MessageEntity } from "../entity/message";
import { MessageEntity } from "../../../../core/chat/entity/message";
export class MessageMapper {
static toDomain(DTO: MessageOutPutDataDTO) : MessageEntity {
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { filter, map } from 'rxjs/operators';
import { InstanceId } from '../chat-service.service';
import { MessageSocketRepositoryService } from 'src/app/module/chat/data/repository/message/message-live-signalr-data-source.service'
import { MessageEntity } from '../entity/message';
import { MessageEntity } from '../../../../core/chat/entity/message';
@Injectable({
providedIn: 'root'
@@ -5,7 +5,7 @@ import { AttachmentLocalDataSource } from 'src/app/module/chat/data/repository/a
import { convertBlobToDataURL } from 'src/app/utils/ToBase64';
import { Result } from 'neverthrow';
import { Logger } from 'src/app/services/logger/main/service';
import { MessageEntity } from '../entity/message';
import { MessageEntity } from '../../../../core/chat/entity/message';
const MessageAttachmentByMessageIdSchema = z.object({
$messageId: z.number(),
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { MessageEntity, MessageEntitySchema, } from '../entity/message';
import { MessageEntity, MessageEntitySchema, } from '../../../../core/chat/entity/message';
import { AttachmentLocalDataSource } from "src/app/module/chat/data/repository/attachment-local-repository.service";
import { z } from 'zod';
import { v4 as uuidv4 } from 'uuid';
@@ -13,8 +13,7 @@ import { MessageSocketRepositoryService } from '../../data/repository/message/me
import { err, Result } from 'neverthrow';
import { MessageTable } from '../../infra/database/dexie/schema/message';
import { MessageMapper } from '../mapper/messageMapper';
import { SignalRService } from '../../infra/socket/signal-r.service';
import { RoomType } from "src/app/module/chat/domain/entity/group";
import { RoomType } from "src/app/core/chat/entity/group";
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member-list-local-repository.service'
import { SessionStore } from 'src/app/store/session.service';
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { MessageEntity } from '../entity/message';
import { MessageEntity } from '../../../../core/chat/entity/message';
import { z } from 'zod';
const MessageInputUseCaseSchema = z.object({
@@ -23,7 +23,7 @@ export class MessageCreateUseCaseService {
// const result = await this.MessageRepositoryService.(input)
// if(result.isOk()) {
// }
// return result
@@ -1,13 +1,17 @@
import { Injectable } from '@angular/core';
import { MessageLocalDataSourceService } from '../../data/repository/message/message-local-data-source.service';
import { MessageSocketRepositoryService } from '../../data/repository/message/message-live-signalr-data-source.service';
import { MessageOutPutDataDTO } from '../../data/dto/message/messageOutputDTO';
import { MessageTable } from '../../infra/database/dexie/schema/message';
import { SignalRService } from '../../infra/socket/signal-r.service';
import { InstanceId } from '../chat-service.service';
import { MessageMapper } from '../mapper/messageMapper';
import { v4 as uuidv4 } from 'uuid'
import { AttachmentLocalDataSource } from '../../data/repository/attachment-local-repository.service';
import { RoomLocalRepository } from '../../data/repository/room/room-local-repository.service';
import { MemberListLocalRepository } from 'src/app/module/chat/data/repository/member-list-local-repository.service'
import { Result } from 'neverthrow';
import { RoomType } from 'src/app/core/chat/entity/group';
import { SessionStore } from 'src/app/store/session.service';
import { MessageOutPutDataDTO } from '../../data/dto/message/messageOutputDTO';
@Injectable({
providedIn: 'root'
@@ -18,19 +22,27 @@ export class SendLocalMessagesUseCaseService {
private MessageSocketRepositoryService: MessageSocketRepositoryService,
private messageLocalDataSourceService: MessageLocalDataSourceService,
private AttachmentRepositoryService: AttachmentLocalDataSource,
private roomLocalDataSourceService: RoomLocalRepository,
private MemberListLocalRepository: MemberListLocalRepository,
private messageSocketRepositoryService: MessageSocketRepositoryService,
) { }
async execute() {
const allRooms = await this.roomLocalDataSourceService.findAll()
const messages = await this.messageLocalDataSourceService.getOfflineMessages()
if(messages.length >= 1) {
if(allRooms.isOk()) {
if(allRooms.value.length == 0) {
for(const message of messages) {
} else {
const attachments = await this.AttachmentRepositoryService.find({$messageId: message.$id})
for(const message of messages) {
const room = allRooms.value.find(e => e.id == message.roomId)
if(attachments.isOk()) {
const attachments = await this.AttachmentRepositoryService.find({$messageId: message.$id})
if(attachments.isOk()) {
message.attachments = attachments.value.map(e => ({
fileType: e.fileType,
@@ -41,14 +53,37 @@ export class SendLocalMessagesUseCaseService {
id: e.id,
mimeType: e.mimeType,
description: e.description,
file: e.file.split(',')[0]
file: e.file.split(',')[1]
}))
console.log('to upload', messages)
const requestId = InstanceId +'@'+ uuidv4();
const DTO = MessageMapper.fromDomain(message, requestId)
await this.messageLocalDataSourceService.update(message.$id, { sending: true })
const sendMessageResult = await this.MessageSocketRepositoryService.sendGroupMessage(DTO)
let sendMessageResult: Result<MessageOutPutDataDTO, any>
if(room.roomType == RoomType.Group) {
const DTO = MessageMapper.fromDomain(message, message.requestId)
sendMessageResult = await this.MessageSocketRepositoryService.sendGroupMessage(DTO)
} else {
if(message.receiverId) {
const DTO = MessageMapper.fromDomain(message, message.requestId)
sendMessageResult = await this.messageSocketRepositoryService.sendDirectMessage(DTO)
} else {
const getRoomMembers = await this.MemberListLocalRepository.directMember({
roomId:message.roomId,
currentUserId: SessionStore.user.UserId
})
if(getRoomMembers.isOk()) {
message.receiverId = getRoomMembers.value.wxUserId
const DTO = MessageMapper.fromDomain(message, message.requestId)
sendMessageResult = await this.messageSocketRepositoryService.sendGroupMessage(DTO)
} else {
console.log('not found direct users', getRoomMembers.error)
}
}
}
if(sendMessageResult.isOk()) {
@@ -63,19 +98,19 @@ export class SendLocalMessagesUseCaseService {
$id : message.$id
}
clone.sending = false
console.log({clone})
console.log('send message local '+ messages.length)
this.messageLocalDataSourceService.update(message.$id, {...clone, sending: false, roomId: message.roomId})
this.messageLocalDataSourceService.update(message.$id, {id: sendMessageResult.value.id, sending: false})
} else {
console.log('erro send message', sendMessageResult.error)
this.messageLocalDataSourceService.update(message.$id, {sending: false})
}
}
}
}
}
}
}
@@ -13,7 +13,7 @@ export class SocketMessageDeleteUseCaseService {
async execute(input: MessageOutPutDataDTO) {
const result = await this.messageLocalDataSourceService.deleteByMessageId(input.id)
const result = await this.messageLocalDataSourceService.update(input.id, { isDeleted: true})
if(result.isOk()) {
@@ -19,7 +19,6 @@ export class SocketMessageUpdateUseCaseService {
async execute(data: MessageOutPutDataDTO, tracing?: TracingType) {
ParamsValidation(MessageOutPutDataDTOSchema, data, tracing)
tracing?.addEvent("Message existe?")
const result = await this.messageLocalDataSourceService.messageExist({id: data.id})
@@ -69,23 +69,23 @@ export class SyncAllRoomMessagesService {
}
}
for(const message of addedItems) {
let clone: MessageTable = message
clone.roomId = room.id
// for(const message of addedItems) {
// let clone: MessageTable = message
// clone.roomId = room.id
const me = message.info.find(e => e.memberId == SessionStore.user.UserId && typeof e.deliverAt == 'string' )
if(!me) {
this.MessageSocketRepositoryService.sendDeliverAt({
memberId: SessionStore.user.UserId,
messageId: message.id,
roomId: message.roomId,
requestId: uuidv4()
})
// const me = message.info.find(e => e.memberId == SessionStore.user.UserId && typeof e.deliverAt == 'string' )
// if(!me) {
// this.MessageSocketRepositoryService.sendDeliverAt({
// memberId: SessionStore.user.UserId,
// messageId: message.id,
// roomId: message.roomId,
// requestId: uuidv4()
// })
tracing.addEvent('send delever roomId'+ room.id)
}
}
// tracing.addEvent('send delever roomId'+ room.id)
// }
// }
this.messageLocalDataSourceService.createManyMessage(addedItems.reverse())
@@ -12,6 +12,7 @@ export const MessageTableSchema = z.object({
oneShot: z.boolean(),
sentAt: z.string().optional(),
editedAt: z.string().nullable().optional(),
isDeleted: z.boolean().optional(),
requireUnlock: z.boolean(),
sender: z.object({
wxUserId: z.number(),
@@ -1,6 +1,6 @@
import { z } from "zod";
import { EntityTable } from 'Dexie';
import { RoomType } from "src/app/module/chat/domain/entity/group";
import { RoomType } from "src/app/core/chat/entity/group";
export const RoomTableSchema = z.object({
id: z.string(),
@@ -4,7 +4,7 @@ import { DexieMessageTable, messageTableColumn, MessageTable } from './schema/me
import { DexieMembersTableSchema, MemberTableColumn } from './schema/members';
import { DexieRoomsTable, RoomTableColumn } from './schema/room';
import { DexieTypingsTable, TypingTableColumn } from './schema/typing';
import { MessageEntity } from '../../../domain/entity/message';
import { MessageEntity } from '../../../../../core/chat/entity/message';
import { AttachmentTableColumn, DexieAttachmentsTableSchema } from './schema/attachment';
// import FDBFactory from 'fake-indexeddb/lib/FDBFactory';
// import FDBKeyRange from 'fake-indexeddb/lib/FDBKeyRange';
@@ -31,4 +31,4 @@ chatDatabase.version(1).stores({
});
chatDatabase.message.mapToClass(MessageEntity)
// Apply in-memory storage
// Apply in-memory storage