1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-04-28 03:20:10 +00:00

Return 409 when gc conflict (#731)

* Return 409 when gc conflict

* Go return 409 when gc conflict

* Return gc conflict when sync repo

---------

Co-authored-by: 杨赫然 <heran.yang@seafile.com>
This commit is contained in:
feiniks 2024-12-30 15:03:54 +08:00 committed by GitHub
parent de62852244
commit ee9ad5ef39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 16 deletions

View File

@ -1745,8 +1745,12 @@ func postMultiFiles(rsp http.ResponseWriter, r *http.Request, repoID, parentDir,
retStr, err := postFilesAndGenCommit(fileNames, repo.ID, user, canonPath, replace, ids, sizes, lastModify, gcID)
if err != nil {
err := fmt.Errorf("failed to post files and gen commit: %v", err)
return &appError{err, "", http.StatusInternalServerError}
if errors.Is(err, ErrGCConflict) {
return &appError{nil, "GC Conflict.\n", http.StatusConflict}
} else {
err := fmt.Errorf("failed to post files and gen commit: %v", err)
return &appError{err, "", http.StatusInternalServerError}
}
}
_, ok := r.Form["ret-json"]
@ -1848,7 +1852,7 @@ retry:
_, err = genNewCommit(repo, headCommit, rootID, user, buf, handleConncurrentUpdate, lastGCID, true)
if err != nil {
if err != ErrConflict {
err := fmt.Errorf("failed to generate new commit: %v", err)
err := fmt.Errorf("failed to generate new commit: %w", err)
return "", err
}
retryCnt++
@ -1907,7 +1911,10 @@ func getCanonPath(p string) string {
return filepath.Join(formatPath)
}
var ErrConflict = fmt.Errorf("Concurent upload conflict")
var (
ErrConflict = errors.New("Concurent upload conflict")
ErrGCConflict = errors.New("GC Conflict")
)
func genNewCommit(repo *repomgr.Repo, base *commitmgr.Commit, newRoot, user, desc string, handleConncurrentUpdate bool, lastGCID string, checkGC bool) (string, error) {
var retryCnt int
@ -2094,7 +2101,7 @@ func updateBranch(repoID, originRepoID, newCommitID, oldCommitID, secondParentID
if lastGCID != gcID.String {
err = fmt.Errorf("Head branch update for repo %s conflicts with GC.", repoID)
trans.Rollback()
return true, err
return true, ErrGCConflict
}
}
@ -3247,8 +3254,12 @@ func putFile(rsp http.ResponseWriter, r *http.Request, repoID, parentDir, user,
desc := fmt.Sprintf("Modified \"%s\"", fileName)
_, err = genNewCommit(repo, headCommit, rootID, user, desc, true, gcID, true)
if err != nil {
err := fmt.Errorf("failed to generate new commit: %v", err)
return &appError{err, "", http.StatusInternalServerError}
if errors.Is(err, ErrGCConflict) {
return &appError{nil, "GC Conflict.\n", http.StatusConflict}
} else {
err := fmt.Errorf("failed to generate new commit: %v", err)
return &appError{err, "", http.StatusInternalServerError}
}
}
if isAjax {
@ -3485,8 +3496,12 @@ func commitFileBlocks(repoID, parentDir, fileName, blockIDsJSON, user string, fi
desc := fmt.Sprintf("Added \"%s\"", fileName)
_, err = genNewCommit(repo, headCommit, rootID, user, desc, true, gcID, true)
if err != nil {
err := fmt.Errorf("failed to generate new commit: %v", err)
return "", &appError{err, "", http.StatusInternalServerError}
if errors.Is(err, ErrGCConflict) {
return "", &appError{nil, "GC Conflict.\n", http.StatusConflict}
} else {
err := fmt.Errorf("failed to generate new commit: %v", err)
return "", &appError{err, "", http.StatusInternalServerError}
}
}
return fileID, nil

View File

@ -1077,8 +1077,12 @@ func putUpdateBranchCB(rsp http.ResponseWriter, r *http.Request) *appError {
token = utils.GetAuthorizationToken(r.Header)
}
if err := fastForwardOrMerge(user, token, repo, base, newCommit); err != nil {
err := fmt.Errorf("Fast forward merge for repo %s is failed: %v", repoID, err)
return &appError{err, "", http.StatusInternalServerError}
if errors.Is(err, ErrGCConflict) {
return &appError{nil, "GC Conflict.\n", http.StatusConflict}
} else {
err := fmt.Errorf("Fast forward merge for repo %s is failed: %v", repoID, err)
return &appError{err, "", http.StatusInternalServerError}
}
}
go mergeVirtualRepoPool.AddTask(repoID, "")

View File

@ -24,5 +24,6 @@
#define POST_FILE_ERR_QUOTA_FULL 519
#define SEAF_ERR_CONCURRENT_UPLOAD 520
#define SEAF_ERR_FILES_WITH_SAME_NAME 521
#define SEAF_ERR_GC_CONFLICT 522
#endif

View File

@ -969,7 +969,8 @@ static int
fast_forward_or_merge (const char *repo_id,
SeafCommit *base,
SeafCommit *new_commit,
const char *token)
const char *token,
gboolean *is_gc_conflict)
{
#define MAX_RETRY_COUNT 3
@ -1086,6 +1087,9 @@ retry:
&gc_conflict) < 0)
{
if (gc_conflict) {
if (is_gc_conflict) {
*is_gc_conflict = TRUE;
}
seaf_warning ("Head branch update for repo %s conflicts with GC.\n",
repo_id);
ret = -1;
@ -1347,9 +1351,16 @@ put_update_branch_cb (evhtp_request_t *req, void *arg)
}
}
if (fast_forward_or_merge (repo_id, base, new_commit, token) < 0) {
seaf_warning ("Fast forward merge for repo %s is failed.\n", repo_id);
evhtp_send_reply (req, EVHTP_RES_SERVERR);
gboolean gc_conflict = FALSE;
if (fast_forward_or_merge (repo_id, base, new_commit, token, &gc_conflict) < 0) {
if (gc_conflict) {
char *msg = "GC Conflict.\n";
evbuffer_add (req->buffer_out, msg, strlen (msg));
evhtp_send_reply (req, EVHTP_RES_CONFLICT);
} else {
seaf_warning ("Fast forward merge for repo %s is failed.\n", repo_id);
evhtp_send_reply (req, EVHTP_RES_SERVERR);
}
goto out;
}

View File

@ -579,7 +579,7 @@ retry:
if (check_gc && gc_conflict) {
seaf_warning ("Head branch update for repo %s conflicts with GC.\n",
repo->id);
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "GC Conflict");
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GC_CONFLICT, "GC Conflict");
ret = -1;
goto out;
}

View File

@ -612,6 +612,9 @@ upload_api_cb(evhtp_request_t *req, void *arg)
} else if (error->code == SEAF_ERR_FILES_WITH_SAME_NAME) {
error_code = -1;
send_error_reply (req, EVHTP_RES_BADREQ, "Too many files with same name.\n");
} else if (error->code == SEAF_ERR_GC_CONFLICT) {
error_code = -1;
send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n");
}
g_clear_error (&error);
}
@ -811,6 +814,9 @@ upload_blks_api_cb(evhtp_request_t *req, void *arg)
error_code = ERROR_BLOCK_MISSING;
} else if (error->code == POST_FILE_ERR_QUOTA_FULL) {
error_code = ERROR_QUOTA;
} else if (error->code == SEAF_ERR_GC_CONFLICT) {
error_code = -1;
send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n");
}
g_clear_error (&error);
}
@ -1243,6 +1249,9 @@ upload_ajax_cb(evhtp_request_t *req, void *arg)
} else if (error->code == SEAF_ERR_FILES_WITH_SAME_NAME) {
error_code = -1;
send_error_reply (req, EVHTP_RES_BADREQ, "Too many files with same name.\n");
} else if (error->code == SEAF_ERR_GC_CONFLICT) {
error_code = -1;
send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n");
}
g_clear_error (&error);
}
@ -1527,6 +1536,9 @@ update_blks_api_cb(evhtp_request_t *req, void *arg)
error_code = ERROR_NOT_EXIST;
} else if (error->code == POST_FILE_ERR_QUOTA_FULL) {
error_code = ERROR_QUOTA;
} else if (error->code == SEAF_ERR_GC_CONFLICT) {
error_code = -1;
send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n");
}
g_clear_error (&error);
}
@ -1788,6 +1800,9 @@ update_ajax_cb(evhtp_request_t *req, void *arg)
if (error) {
if (g_strcmp0 (error->message, "file does not exist") == 0) {
error_code = ERROR_NOT_EXIST;
} else if (error->code == SEAF_ERR_GC_CONFLICT) {
error_code = -1;
send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n");
}
g_clear_error (&error);
}