diff options
author | 2022-03-07 11:08:26 +0100 | |
---|---|---|
committer | 2022-03-07 11:08:26 +0100 | |
commit | 07727753b96d209406783e5e539725bcdafebdc7 (patch) | |
tree | b32f11cbc304d633ed0acd8f84b4c11e909bb5f3 /vendor/github.com/robfig/cron/v3/spec.go | |
parent | [documentation] Creates Docker documentation and docker-compose.yaml (#416) (diff) | |
download | gotosocial-07727753b96d209406783e5e539725bcdafebdc7.tar.xz |
[feature] Clean up/uncache remote media (#407)
* Add whereNotEmptyAndNotNull
* Add GetRemoteOlderThanDays
* Add GetRemoteOlderThanDays
* Add PruneRemote to Manager interface
* Start implementing PruneRemote
* add new attachment + status to tests
* fix up and test GetRemoteOlderThan
* fix bad import
* PruneRemote: return number pruned
* add Cached column to mediaattachment
* update + test pruneRemote
* update mediaTest
* use Cached column
* upstep bun to latest version
* embed structs in mediaAttachment
* migrate mediaAttachment to new format
* don't default cached to true
* select only remote media
* update db dependencies
* step bun back to last working version
* update pruneRemote to use Cached field
* fix storage path of test attachments
* add recache logic to manager
* fix trimmed aspect ratio
* test prune and recache
* return errwithcode
* tidy up different paths for emoji vs attachment
* fix incorrect thumbnail type being stored
* expose TransportController to media processor
* implement tee-ing recached content
* add thoughts of dog to test fedi attachments
* test get remote files
* add comment on PruneRemote
* add postData cleanup to recache
* test thumbnail fetching
* add incredible diagram
* go mod tidy
* buffer pipes for recache streaming
* test for client stops reading after 1kb
* add media-remote-cache-days to config
* add cron package
* wrap logrus so it's available to cron
* start and stop cron jobs gracefully
Diffstat (limited to 'vendor/github.com/robfig/cron/v3/spec.go')
-rw-r--r-- | vendor/github.com/robfig/cron/v3/spec.go | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/vendor/github.com/robfig/cron/v3/spec.go b/vendor/github.com/robfig/cron/v3/spec.go new file mode 100644 index 000000000..fa1e241e5 --- /dev/null +++ b/vendor/github.com/robfig/cron/v3/spec.go @@ -0,0 +1,188 @@ +package cron + +import "time" + +// SpecSchedule specifies a duty cycle (to the second granularity), based on a +// traditional crontab specification. It is computed initially and stored as bit sets. +type SpecSchedule struct { + Second, Minute, Hour, Dom, Month, Dow uint64 + + // Override location for this schedule. + Location *time.Location +} + +// bounds provides a range of acceptable values (plus a map of name to value). +type bounds struct { + min, max uint + names map[string]uint +} + +// The bounds for each field. +var ( + seconds = bounds{0, 59, nil} + minutes = bounds{0, 59, nil} + hours = bounds{0, 23, nil} + dom = bounds{1, 31, nil} + months = bounds{1, 12, map[string]uint{ + "jan": 1, + "feb": 2, + "mar": 3, + "apr": 4, + "may": 5, + "jun": 6, + "jul": 7, + "aug": 8, + "sep": 9, + "oct": 10, + "nov": 11, + "dec": 12, + }} + dow = bounds{0, 6, map[string]uint{ + "sun": 0, + "mon": 1, + "tue": 2, + "wed": 3, + "thu": 4, + "fri": 5, + "sat": 6, + }} +) + +const ( + // Set the top bit if a star was included in the expression. + starBit = 1 << 63 +) + +// Next returns the next time this schedule is activated, greater than the given +// time. If no time can be found to satisfy the schedule, return the zero time. +func (s *SpecSchedule) Next(t time.Time) time.Time { + // General approach + // + // For Month, Day, Hour, Minute, Second: + // Check if the time value matches. If yes, continue to the next field. + // If the field doesn't match the schedule, then increment the field until it matches. + // While incrementing the field, a wrap-around brings it back to the beginning + // of the field list (since it is necessary to re-verify previous field + // values) + + // Convert the given time into the schedule's timezone, if one is specified. + // Save the original timezone so we can convert back after we find a time. + // Note that schedules without a time zone specified (time.Local) are treated + // as local to the time provided. + origLocation := t.Location() + loc := s.Location + if loc == time.Local { + loc = t.Location() + } + if s.Location != time.Local { + t = t.In(s.Location) + } + + // Start at the earliest possible time (the upcoming second). + t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond) + + // This flag indicates whether a field has been incremented. + added := false + + // If no time is found within five years, return zero. + yearLimit := t.Year() + 5 + +WRAP: + if t.Year() > yearLimit { + return time.Time{} + } + + // Find the first applicable month. + // If it's this month, then do nothing. + for 1<<uint(t.Month())&s.Month == 0 { + // If we have to add a month, reset the other parts to 0. + if !added { + added = true + // Otherwise, set the date at the beginning (since the current time is irrelevant). + t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, loc) + } + t = t.AddDate(0, 1, 0) + + // Wrapped around. + if t.Month() == time.January { + goto WRAP + } + } + + // Now get a day in that month. + // + // NOTE: This causes issues for daylight savings regimes where midnight does + // not exist. For example: Sao Paulo has DST that transforms midnight on + // 11/3 into 1am. Handle that by noticing when the Hour ends up != 0. + for !dayMatches(s, t) { + if !added { + added = true + t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc) + } + t = t.AddDate(0, 0, 1) + // Notice if the hour is no longer midnight due to DST. + // Add an hour if it's 23, subtract an hour if it's 1. + if t.Hour() != 0 { + if t.Hour() > 12 { + t = t.Add(time.Duration(24-t.Hour()) * time.Hour) + } else { + t = t.Add(time.Duration(-t.Hour()) * time.Hour) + } + } + + if t.Day() == 1 { + goto WRAP + } + } + + for 1<<uint(t.Hour())&s.Hour == 0 { + if !added { + added = true + t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, loc) + } + t = t.Add(1 * time.Hour) + + if t.Hour() == 0 { + goto WRAP + } + } + + for 1<<uint(t.Minute())&s.Minute == 0 { + if !added { + added = true + t = t.Truncate(time.Minute) + } + t = t.Add(1 * time.Minute) + + if t.Minute() == 0 { + goto WRAP + } + } + + for 1<<uint(t.Second())&s.Second == 0 { + if !added { + added = true + t = t.Truncate(time.Second) + } + t = t.Add(1 * time.Second) + + if t.Second() == 0 { + goto WRAP + } + } + + return t.In(origLocation) +} + +// dayMatches returns true if the schedule's day-of-week and day-of-month +// restrictions are satisfied by the given time. +func dayMatches(s *SpecSchedule, t time.Time) bool { + var ( + domMatch bool = 1<<uint(t.Day())&s.Dom > 0 + dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0 + ) + if s.Dom&starBit > 0 || s.Dow&starBit > 0 { + return domMatch && dowMatch + } + return domMatch || dowMatch +} |