code.gitea.io/gitea@v1.21.7/services/mirror/mirror.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package mirror 5 6 import ( 7 "context" 8 "fmt" 9 10 repo_model "code.gitea.io/gitea/models/repo" 11 "code.gitea.io/gitea/modules/graceful" 12 "code.gitea.io/gitea/modules/log" 13 "code.gitea.io/gitea/modules/queue" 14 "code.gitea.io/gitea/modules/setting" 15 ) 16 17 // doMirrorSync causes this request to mirror itself 18 func doMirrorSync(ctx context.Context, req *SyncRequest) { 19 if req.ReferenceID == 0 { 20 log.Warn("Skipping mirror sync request, no mirror ID was specified") 21 return 22 } 23 switch req.Type { 24 case PushMirrorType: 25 _ = SyncPushMirror(ctx, req.ReferenceID) 26 case PullMirrorType: 27 _ = SyncPullMirror(ctx, req.ReferenceID) 28 default: 29 log.Error("Unknown Request type in queue: %v for MirrorID[%d]", req.Type, req.ReferenceID) 30 } 31 } 32 33 var errLimit = fmt.Errorf("reached limit") 34 35 // Update checks and updates mirror repositories. 36 func Update(ctx context.Context, pullLimit, pushLimit int) error { 37 if !setting.Mirror.Enabled { 38 log.Warn("Mirror feature disabled, but cron job enabled: skip update") 39 return nil 40 } 41 log.Trace("Doing: Update") 42 43 handler := func(idx int, bean any) error { 44 var repo *repo_model.Repository 45 var mirrorType SyncType 46 var referenceID int64 47 48 if m, ok := bean.(*repo_model.Mirror); ok { 49 if m.GetRepository(ctx) == nil { 50 log.Error("Disconnected mirror found: %d", m.ID) 51 return nil 52 } 53 repo = m.Repo 54 mirrorType = PullMirrorType 55 referenceID = m.RepoID 56 } else if m, ok := bean.(*repo_model.PushMirror); ok { 57 if m.GetRepository() == nil { 58 log.Error("Disconnected push-mirror found: %d", m.ID) 59 return nil 60 } 61 repo = m.Repo 62 mirrorType = PushMirrorType 63 referenceID = m.ID 64 } else { 65 log.Error("Unknown bean: %v", bean) 66 return nil 67 } 68 69 // Check we've not been cancelled 70 select { 71 case <-ctx.Done(): 72 return fmt.Errorf("aborted") 73 default: 74 } 75 76 // Push to the Queue 77 if err := PushToQueue(mirrorType, referenceID); err != nil { 78 if err == queue.ErrAlreadyInQueue { 79 if mirrorType == PushMirrorType { 80 log.Trace("PushMirrors for %-v already queued for sync", repo) 81 } else { 82 log.Trace("PullMirrors for %-v already queued for sync", repo) 83 } 84 return nil 85 } 86 return err 87 } 88 return nil 89 } 90 91 pullMirrorsRequested := 0 92 if pullLimit != 0 { 93 if err := repo_model.MirrorsIterate(ctx, pullLimit, func(idx int, bean any) error { 94 if err := handler(idx, bean); err != nil { 95 return err 96 } 97 pullMirrorsRequested++ 98 return nil 99 }); err != nil && err != errLimit { 100 log.Error("MirrorsIterate: %v", err) 101 return err 102 } 103 } 104 105 pushMirrorsRequested := 0 106 if pushLimit != 0 { 107 if err := repo_model.PushMirrorsIterate(ctx, pushLimit, func(idx int, bean any) error { 108 if err := handler(idx, bean); err != nil { 109 return err 110 } 111 pushMirrorsRequested++ 112 return nil 113 }); err != nil && err != errLimit { 114 log.Error("PushMirrorsIterate: %v", err) 115 return err 116 } 117 } 118 log.Trace("Finished: Update: %d pull mirrors and %d push mirrors queued", pullMirrorsRequested, pushMirrorsRequested) 119 return nil 120 } 121 122 func queueHandler(items ...*SyncRequest) []*SyncRequest { 123 for _, req := range items { 124 doMirrorSync(graceful.GetManager().ShutdownContext(), req) 125 } 126 return nil 127 } 128 129 // InitSyncMirrors initializes a go routine to sync the mirrors 130 func InitSyncMirrors() { 131 StartSyncMirrors(queueHandler) 132 }