Put initial prototype code under version control
parent
f734ccfeee
commit
3a83607a2d
@ -0,0 +1,156 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StringSlice sort.StringSlice
|
||||
|
||||
type Job struct {
|
||||
Id uint
|
||||
Archived bool
|
||||
Customer string
|
||||
Name string
|
||||
Taxa []string
|
||||
Tags sort.StringSlice
|
||||
Watching sort.StringSlice
|
||||
Notified map[string]time.Time
|
||||
}
|
||||
|
||||
func NewJob(id uint, customer string, name string) *Job {
|
||||
job := &Job{
|
||||
Id: id,
|
||||
Archived: false,
|
||||
Customer: customer,
|
||||
Name: name,
|
||||
Taxa: sort.StringSlice{},
|
||||
Tags: sort.StringSlice{},
|
||||
Watching: sort.StringSlice{},
|
||||
Notified: map[string]time.Time{},
|
||||
}
|
||||
return job
|
||||
}
|
||||
|
||||
func union(slices ...sort.StringSlice) sort.StringSlice {
|
||||
set := map[string]bool{}
|
||||
for _, slice := range slices {
|
||||
for _, key := range slice {
|
||||
set[key] = true
|
||||
}
|
||||
}
|
||||
keys := make(sort.StringSlice, len(set))
|
||||
i := 0
|
||||
for key, _ := range set {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
keys.Sort()
|
||||
return keys
|
||||
}
|
||||
|
||||
func (job *Job) AddTaxa(taxa ...string) {
|
||||
job.Taxa = append(job.Taxa, taxa...)
|
||||
}
|
||||
|
||||
func (job *Job) AddTags(tags ...string) {
|
||||
job.Tags = union(job.Tags, tags)
|
||||
}
|
||||
|
||||
func (job *Job) Watch(who ...string) {
|
||||
job.Watching = union(job.Watching, who)
|
||||
}
|
||||
|
||||
func (job *Job) Notify(who ...string) {
|
||||
for _, user := range who {
|
||||
job.Notified[user] = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
func (job *Job) Shard() string {
|
||||
upper := job.Id / 1000
|
||||
return fmt.Sprintf("%dxxx", upper)
|
||||
}
|
||||
|
||||
func (job *Job) Path() string {
|
||||
return fmt.Sprintf("Jobs/%s/%d", job.Shard(), job.Id)
|
||||
}
|
||||
|
||||
func (job *Job) TaxonomyDirectories() sort.StringSlice {
|
||||
n := len(job.Taxa)
|
||||
parts := make([][]string, (n*n+n)/2)
|
||||
|
||||
// e.g. [x,y,z] -> [[x], [x, y], [x, y, z]]
|
||||
for i := range job.Taxa {
|
||||
parts[i] = job.Taxa[0 : i+1]
|
||||
}
|
||||
|
||||
// e.g. [[x], [x, y], [x, y, z]] -> [[y], [y, z]] + [[z]]
|
||||
k := n
|
||||
for i := 1; i < n; i++ {
|
||||
for j := i; j < n; j++ {
|
||||
parts[k] = job.Taxa[i : j+1]
|
||||
k++
|
||||
}
|
||||
}
|
||||
|
||||
dirs := make([]string, k)
|
||||
upper := job.Id / 1000
|
||||
for i, part := range parts {
|
||||
dirs[i] = fmt.Sprintf("Customers/%s/%s/• Jobs/%dxxx", job.Customer, strings.Join(part, "/"), upper)
|
||||
}
|
||||
return dirs
|
||||
}
|
||||
|
||||
func (job *Job) CustomerDirectory() string {
|
||||
return fmt.Sprintf("Customers/%s/• Jobs/%s", job.Customer, job.Shard())
|
||||
}
|
||||
|
||||
func (job *Job) SymlinkDirectories() sort.StringSlice {
|
||||
customer := sort.StringSlice{job.CustomerDirectory()}
|
||||
taxonomy := job.TaxonomyDirectories()
|
||||
|
||||
return union(customer, taxonomy)
|
||||
}
|
||||
|
||||
func (job *Job) AllDirectories() sort.StringSlice {
|
||||
original := sort.StringSlice{job.Path()}
|
||||
symlinks := job.SymlinkDirectories()
|
||||
|
||||
return union(original, symlinks)
|
||||
}
|
||||
|
||||
func (job *Job) Description() string {
|
||||
return fmt.Sprintf("%d | %s | %s", job.Id, strings.Join(job.Taxa, " ▶ "), job.Name)
|
||||
}
|
||||
|
||||
func (job *Job) Create(where string) error {
|
||||
for _, dir := range job.AllDirectories() {
|
||||
err := os.MkdirAll(where+"/"+dir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
original := job.Path()
|
||||
description := job.Description()
|
||||
for _, dir := range job.SymlinkDirectories() {
|
||||
err := os.Remove(where + "/" + dir + "/." + description)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
err = os.Symlink(where+"/"+original, where+"/"+dir+"/."+description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Rename(where+"/"+dir+"/."+description, where+"/"+dir+"/"+description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue