mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-25 17:42:24 +08:00
feat: Implement API of ragflow server in Go (#15256)
## Summary
- Implemented the Go API endpoint for Memory message forgetting:
- `DELETE /api/v1/messages/{memory_id}:{message_id}`
- Added route registration for the Memory message DELETE endpoint only.
- Added request path validation for `memory_id:message_id`.
- Added service logic to mark a message as forgotten by setting
`forget_at`.
- Preserved Python-compatible response behavior:
- Success returns `code: 0`, `message: true`, `data: null`.
- Added focused unit tests for message path parsing and invalid message
ID handling.
- Fixed Linux cgo linker config to use the installed shared PCRE2
library so Go tests/builds can run in this environment.
## Related Issue
Closes: #15240
## Change Type
- [x] Feature
- [x] Test
- [x] Build / CI compatibility
## Implemented API
- `DELETE /api/v1/messages/{memory_id}:{message_id}`
## Real Behavior Proof
Validated with targeted Go tests:
```bash
/tmp/go1.25.0/bin/go test ./internal/handler ./internal/router
```
Result:
```text
ok ragflow/internal/handler
? ragflow/internal/router [no test files]
```
Validated server entrypoint build:
```bash
/tmp/go1.25.0/bin/go build -o /tmp/ragflow-server-main ./cmd/server_main.go
```
Result:
```text
build succeeded
```
Validated patch formatting:
```bash
git diff --check
```
Result:
```text
no whitespace errors
```
## Checklist
- [x] Implemented only `DELETE
/api/v1/messages/{memory_id}:{message_id}`.
- [x] Did not implement unrelated Memory message APIs.
- [x] Added route registration.
- [x] Added handler validation.
- [x] Added service-level memory access check.
- [x] Added tests.
- [x] Ran targeted Go tests.
- [x] Ran server build validation.
- [x] Ran `git diff --check`.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -549,8 +550,8 @@ func (h *MemoryHandler) AddMessage(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// ForgetMessage handles DELETE request for forgetting messages
|
||||
// API Path: DELETE /api/v1/messages/:memory_id/:message_id
|
||||
// ForgetMessage handles DELETE request for forgetting messages.
|
||||
// API Path: DELETE /api/v1/messages/{memory_id}:{message_id}
|
||||
//
|
||||
// Function:
|
||||
// - Soft-deletes the specified message (sets forget_at timestamp)
|
||||
@@ -559,16 +560,82 @@ func (h *MemoryHandler) AddMessage(c *gin.Context) {
|
||||
// Parameter Format:
|
||||
// - memory_id: Memory ID
|
||||
// - message_id: Message ID (integer)
|
||||
//
|
||||
// TODO: Implementation pending - depends on embedding engine
|
||||
func (h *MemoryHandler) ForgetMessage(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
memoryID, messageID, err := parseMemoryMessagePath(c.Param("memory_message"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": common.CodeArgumentError,
|
||||
"message": err.Error(),
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.memoryService.ForgetMessage(c.Request.Context(), user.ID, memoryID, messageID); err != nil {
|
||||
errMsg := err.Error()
|
||||
if isMemoryServiceNotFound(err) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": common.CodeNotFound,
|
||||
"message": errMsg,
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": common.CodeServerError,
|
||||
"message": "Internal server error",
|
||||
"data": nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": common.CodeServerError,
|
||||
"message": "ForgetMessage not implemented - pending embedding engine dependency",
|
||||
"code": common.CodeSuccess,
|
||||
"message": true,
|
||||
"data": nil,
|
||||
})
|
||||
}
|
||||
|
||||
func isMemoryServiceNotFound(err error) bool {
|
||||
var notFoundErr *service.ResourceNotFoundError
|
||||
return errors.As(err, ¬FoundErr) && notFoundErr.Resource == "Memory"
|
||||
}
|
||||
|
||||
func parseMemoryMessagePath(memoryMessage string) (string, int64, error) {
|
||||
memoryMessage = strings.TrimSpace(memoryMessage)
|
||||
if memoryMessage == "" {
|
||||
return "", 0, errors.New("memory_id and message_id are required")
|
||||
}
|
||||
|
||||
parts := strings.Split(memoryMessage, ":")
|
||||
if len(parts) != 2 {
|
||||
return "", 0, errors.New("message path must be formatted as memory_id:message_id")
|
||||
}
|
||||
|
||||
memoryID := strings.TrimSpace(parts[0])
|
||||
messageIDText := strings.TrimSpace(parts[1])
|
||||
if memoryID == "" {
|
||||
return "", 0, errors.New("memory_id is required")
|
||||
}
|
||||
if messageIDText == "" {
|
||||
return "", 0, errors.New("message_id is required")
|
||||
}
|
||||
|
||||
messageID, err := strconv.ParseInt(messageIDText, 10, 64)
|
||||
if err != nil || messageID < 0 {
|
||||
return "", 0, errors.New("message_id must be a non-negative integer")
|
||||
}
|
||||
|
||||
return memoryID, messageID, nil
|
||||
}
|
||||
|
||||
// UpdateMessage handles PUT request for updating message status
|
||||
// API Path: PUT /api/v1/messages/:memory_id/:message_id
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user