mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-11-14 08:17:26 +01:00
88 lines
3.3 KiB
Go
88 lines
3.3 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/tdurieux/anonymous_github/backend/internal/provider"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
|
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
|
)
|
|
|
|
func (g *githubProvider) cachedRepositories(ctx context.Context, user M) ([]provider.Repository, error) {
|
|
ids := []bson.ObjectID{}
|
|
for _, value := range arr(user["repositories"]) {
|
|
if id, err := oid(str(value)); err == nil {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
// Match TypeScript's find($in) behavior: database order, unique rows, and
|
|
// missing references omitted. Other providers never enter GitHub discovery.
|
|
rows, err := g.server.Store.list(ctx, "repositories", M{"_id": M{"$in": ids}, "externalId": M{"$regex": "^gh_"}}, 0, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out := []provider.Repository{}
|
|
for _, row := range rows {
|
|
out = append(out, provider.Repository{ID: strings.TrimPrefix(str(row["externalId"]), "gh_"), Name: str(row["name"]), URL: str(row["url"]), Size: number(row["size"]), DefaultBranch: str(row["defaultBranch"]), HasPage: boolean(row["hasPage"])})
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (g *githubProvider) cacheRepositories(ctx context.Context, user M, repos []provider.Repository) error {
|
|
ids := []bson.ObjectID{}
|
|
externalIDs := make([]string, 0, len(repos))
|
|
for _, repo := range repos {
|
|
externalIDs = append(externalIDs, externalRepositoryID("github", repo.ID))
|
|
}
|
|
existing, err := g.server.Store.list(ctx, "repositories", M{"externalId": M{"$in": externalIDs}}, 0, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
byExternalID := map[string]M{}
|
|
for _, row := range existing {
|
|
byExternalID[str(row["externalId"])] = row
|
|
}
|
|
for _, repo := range repos {
|
|
external := externalRepositoryID("github", repo.ID)
|
|
cached := byExternalID[external]
|
|
if cached == nil {
|
|
// TypeScript reuses existing rows without overwriting their metadata.
|
|
// Atomic insertion also prevents duplicate rows from concurrent discovery.
|
|
insert := M{"_id": bson.NewObjectID(), "externalId": external, "name": repo.Name, "url": repo.URL, "size": repo.Size, "defaultBranch": repo.DefaultBranch, "source": "github", "hasPage": false, "status": "ready", "branches": []any{}, "dateOfEntry": time.Now(), "__v": 0}
|
|
err := g.server.Store.DB.Collection("repositories").FindOneAndUpdate(ctx, M{"externalId": external}, M{"$setOnInsert": insert}, options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After)).Decode(&cached)
|
|
if mongo.IsDuplicateKeyError(err) {
|
|
cached, err = g.server.Store.one(ctx, "repositories", M{"externalId": external})
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
byExternalID[external] = cached
|
|
}
|
|
id, err := oid(str(cached["_id"]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ids = append(ids, id)
|
|
}
|
|
filter := M{"_id": user["_id"], "status": user["status"]}
|
|
if revision, ok := user["repositoryDiscoveryRevision"]; ok {
|
|
filter["repositoryDiscoveryRevision"] = revision
|
|
} else {
|
|
filter["repositoryDiscoveryRevision"] = M{"$exists": false}
|
|
}
|
|
// Reconnecting/disconnecting while discovery is in flight invalidates this
|
|
// publication, including when the old and new saved lists are both empty.
|
|
matched, err := g.server.Store.update(ctx, "users", filter, M{"$set": M{"repositories": ids}})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !matched {
|
|
return fail("connection_changed", 409)
|
|
}
|
|
return nil
|
|
}
|