github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/sharing/reupload.go (about) 1 package sharing 2 3 import ( 4 "net/http" 5 "net/url" 6 7 "github.com/cozy/cozy-stack/client/request" 8 "github.com/cozy/cozy-stack/model/instance" 9 "github.com/cozy/cozy-stack/model/instance/lifecycle" 10 "github.com/cozy/cozy-stack/pkg/consts" 11 "github.com/cozy/cozy-stack/pkg/couchdb" 12 multierror "github.com/hashicorp/go-multierror" 13 ) 14 15 func init() { 16 lifecycle.AskReupload = AskReupload 17 } 18 19 // AskReupload is used when the disk quota of an instance is increased to tell 20 // to the other instances that have a sharing with it that they can retry to 21 // upload files. 22 func AskReupload(inst *instance.Instance) error { 23 // XXX If there are more than 100 sharings, it is probably better to rely 24 // on the existing retry mechanism than asking for all of the sharings, as 25 // it may slow down the sharings. 26 req := &couchdb.AllDocsRequest{ 27 Limit: 100, 28 } 29 var sharings []*Sharing 30 err := couchdb.GetAllDocs(inst, consts.Sharings, req, &sharings) 31 if err != nil { 32 return err 33 } 34 var errm error 35 for _, s := range sharings { 36 if !s.Active || s.FirstFilesRule() == nil { 37 continue 38 } 39 if s.Owner { 40 for i, m := range s.Members { 41 if i == 0 { 42 continue // skip the owner 43 } 44 if m.Status != MemberStatusReady { 45 continue 46 } 47 if err := askReuploadTo(inst, s, &s.Members[i], &s.Credentials[i-1]); err != nil { 48 errm = multierror.Append(errm, err) 49 } 50 } 51 52 continue 53 } 54 55 if len(s.Credentials) > 0 { 56 if err := askReuploadTo(inst, s, &s.Members[0], &s.Credentials[0]); err != nil { 57 errm = multierror.Append(errm, err) 58 } 59 } 60 } 61 return errm 62 } 63 64 func askReuploadTo(inst *instance.Instance, s *Sharing, m *Member, c *Credentials) error { 65 if c == nil || c.AccessToken == nil { 66 return nil 67 } 68 u, err := url.Parse(m.Instance) 69 if err != nil { 70 return err 71 } 72 opts := &request.Options{ 73 Method: http.MethodPost, 74 Scheme: u.Scheme, 75 Domain: u.Host, 76 Path: "/sharings/" + s.SID + "/reupload", 77 Headers: request.Headers{ 78 "Authorization": "Bearer " + c.AccessToken.AccessToken, 79 }, 80 ParseError: ParseRequestError, 81 } 82 res, err := request.Req(opts) 83 if res != nil && res.StatusCode/100 == 4 { 84 res, err = RefreshToken(inst, err, s, m, c, opts, nil) 85 } 86 if err != nil { 87 return err 88 } 89 defer res.Body.Close() 90 return nil 91 } 92 93 // PushUploadJob pushs a job for the share-upload worker, to try again to 94 // reupload files. 95 func PushUploadJob(s *Sharing, inst *instance.Instance) { 96 if s.Active && s.FirstFilesRule() != nil { 97 s.pushJob(inst, "share-upload") 98 } 99 }