Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
72 changes: 72 additions & 0 deletions graph/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,78 @@ const docTemplate = `{
}
}
},
"/connections/delete": {
"post": {
"description": "문서 간의 그래프 연결을 삭제합니다.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Graph Connection"
],
"summary": "그래프 연결 삭제",
"parameters": [
{
"description": "삭제할 Source 문서 ID 및 Target 문서 ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"type": "object",
"properties": {
"sourceId": {
"type": "string"
},
"targetId": {
"type": "string"
},
"workspaceId": {
"type": "string"
}
}
}
}
],
"responses": {
"200": {
"description": "연결 삭제 성공",
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string"
}
}
}
},
"400": {
"description": "잘못된 요청 형식",
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
}
}
},
"500": {
"description": "서버 내부 오류로 연결 삭제 실패",
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
}
}
}
}
}
},
"/connections/edit": {
"post": {
"description": "사용자가 문서 간의 연결을 수동으로 편집했음을 표시하기 위해 연결 상태를 'edited'로 변경합니다.",
Expand Down
72 changes: 72 additions & 0 deletions graph/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,78 @@
}
}
},
"/connections/delete": {
"post": {
"description": "문서 간의 그래프 연결을 삭제합니다.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Graph Connection"
],
"summary": "그래프 연결 삭제",
"parameters": [
{
"description": "삭제할 Source 문서 ID 및 Target 문서 ID",
"name": "request",
"in": "body",
"required": true,
"schema": {
"type": "object",
"properties": {
"sourceId": {
"type": "string"
},
"targetId": {
"type": "string"
},
"workspaceId": {
"type": "string"
}
}
}
}
],
"responses": {
"200": {
"description": "연결 삭제 성공",
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string"
}
}
}
},
"400": {
"description": "잘못된 요청 형식",
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
}
}
},
"500": {
"description": "서버 내부 오류로 연결 삭제 실패",
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
}
}
}
}
}
},
"/connections/edit": {
"post": {
"description": "사용자가 문서 간의 연결을 수동으로 편집했음을 표시하기 위해 연결 상태를 'edited'로 변경합니다.",
Expand Down
46 changes: 46 additions & 0 deletions graph/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,52 @@ paths:
summary: 그래프 연결 확정
tags:
- Graph Connection
/connections/delete:
post:
consumes:
- application/json
description: 문서 간의 그래프 연결을 삭제합니다.
parameters:
- description: 삭제할 Source 문서 ID 및 Target 문서 ID
in: body
name: request
required: true
schema:
properties:
sourceId:
type: string
targetId:
type: string
workspaceId:
type: string
type: object
produces:
- application/json
responses:
"200":
description: 연결 삭제 성공
schema:
properties:
status:
type: string
type: object
"400":
description: 잘못된 요청 형식
schema:
properties:
error:
type: string
type: object
"500":
description: 서버 내부 오류로 연결 삭제 실패
schema:
properties:
error:
type: string
type: object
summary: 그래프 연결 삭제
tags:
- Graph Connection
/connections/edit:
post:
consumes:
Expand Down
28 changes: 28 additions & 0 deletions graph/handlers/graph_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,34 @@ func (h *GraphConnectionHandler) EditGraphConnection(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "success"})
}

// DeleteGraphConnection
// @Summary 그래프 연결 삭제
// @Description 문서 간의 그래프 연결을 삭제합니다.
// @Tags Graph Connection
// @Accept json
// @Produce json
// @Param request body object{sourceId=string,targetId=string,workspaceId=string} true "삭제할 Source 문서 ID 및 Target 문서 ID"
// @Success 200 {object} object{status=string} "연결 삭제 성공"
// @Failure 400 {object} object{error=string} "잘못된 요청 형식"
// @Failure 500 {object} object{error=string} "서버 내부 오류로 연결 삭제 실패"
// @Router /connections/delete [post]
func (h *GraphConnectionHandler) DeleteGraphConnection(c *gin.Context) {
var req struct {
SourceID string `json:"sourceId" binding:"required"`
TargetID string `json:"targetId" binding:"required"`
WorkspaceID string `json:"workspaceId" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := h.service.DeleteGraphConnection(c.Request.Context(), req.SourceID, req.TargetID, req.WorkspaceID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to delete connection: %s", err.Error())})
return
}
c.JSON(http.StatusOK, gin.H{"status": "success"})
}

// DeleteNoteGraph
// @Summary 노트 삭제 이벤트 처리
// @Description 외부 노트 서비스에서 노트 삭제 시 관련 그래프 연결을 모두 삭제합니다.
Expand Down
1 change: 1 addition & 0 deletions graph/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func NewServer(gs *services.GraphService, ws *services.WorkspaceService) *gin.En
// 그래프 연결 관리
router.POST("/connections/confirm", graphHandler.ConfirmGraphConnection)
router.POST("/connections/edit", graphHandler.EditGraphConnection)
router.POST("/connections/delete", graphHandler.DeleteGraphConnection)
router.POST("/connections/note-deleted", graphHandler.DeleteNoteGraph)
router.POST("/workspaces/:workspaceId/clear-pending", graphHandler.ClearPendingConnections)

Expand Down
16 changes: 16 additions & 0 deletions graph/services/graph_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,22 @@ func (s *GraphService) EditGraphConnection(ctx context.Context, sourceID, target
return err
}

func (s *GraphService) DeleteGraphConnection(ctx context.Context, sourceID, targetID, workspaceID string) error {
result, err := s.db.Collection("graph_connections").DeleteOne(
ctx, bson.M{"workspace_id": workspaceID, "source_id": sourceID, "target_id": targetID},
)
if err != nil {
return fmt.Errorf("failed to delete graph connection: %w", err)
}

if result.DeletedCount == 0 {
log.Printf("[DeleteGraphConnection] No connection found for (%s -> %s) in WS %s", sourceID, targetID, workspaceID)
}

log.Printf("[DeleteGraphConnection] Deleted (%s -> %s) from WS %s", sourceID, targetID, workspaceID)
return nil
}

func (s *GraphService) ConfirmAllConnections(ctx context.Context, workspaceID string) error {
_, err := s.db.Collection("graph_connections").UpdateMany(
ctx,
Expand Down
52 changes: 52 additions & 0 deletions graph/services/graph_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,58 @@ func TestGraphService_ConfirmGraphConnection(t *testing.T) {
})
}

func TestGraphService_DeleteGraphConnection(t *testing.T) {
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
sourceID := "6517a2624a081a27e7d0f93a"
targetID := "6517a2624a081a27e7d0f93b"
workspaceID := "workspace1"
ctx := context.Background()

mt.Run("Success_DeletesSingleConnection", func(mt *mtest.T) {
service := services.NewGraphService(mt.DB)

mt.AddMockResponses(
mtest.CreateSuccessResponse(
bson.E{Key: "ok", Value: 1},
bson.E{Key: "n", Value: 1},
bson.E{Key: "deletedCount", Value: 1},
),
)

err := service.DeleteGraphConnection(ctx, sourceID, targetID, workspaceID)
assert.NoError(t, err)
})

mt.Run("Success_NoConnectionFound", func(mt *mtest.T) {
service := services.NewGraphService(mt.DB)

mt.AddMockResponses(
mtest.CreateSuccessResponse(
bson.E{Key: "ok", Value: 1},
bson.E{Key: "n", Value: 0},
bson.E{Key: "deletedCount", Value: 0},
),
)

err := service.DeleteGraphConnection(ctx, sourceID, targetID, workspaceID)
assert.NoError(t, err, "no data but should not return error")
})

mt.Run("Error_DeleteOperationFailed", func(mt *mtest.T) {
service := services.NewGraphService(mt.DB)
mt.AddMockResponses(
mtest.CreateCommandErrorResponse(mtest.CommandError{
Message: "delete failed",
Code: 11000,
}),
)

err := service.DeleteGraphConnection(ctx, sourceID, targetID, workspaceID)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to delete graph connection")
})
}

func TestGraphService_ConfirmAllConnections(t *testing.T) {
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
workspaceID := "6517a2624a081a27e7d0f91e"
Expand Down
Loading