use cache interface for some more things

This commit is contained in:
Ted Unangst 2019-10-07 14:45:02 -04:00
parent 5c0b7f1973
commit b1e42fdae9
5 changed files with 71 additions and 100 deletions

View File

@ -29,7 +29,6 @@ import (
"os" "os"
"regexp" "regexp"
"strings" "strings"
"sync"
"time" "time"
"humungus.tedunangst.com/r/webs/htfilter" "humungus.tedunangst.com/r/webs/htfilter"
@ -257,40 +256,24 @@ type Box struct {
Shared string Shared string
} }
var boxofboxes = make(map[string]*Box) var boxofboxes = cacheNew(cacheOptions{Filler: func(ident string) (*Box, bool) {
var boxlock sync.Mutex
var boxinglock sync.Mutex
func getboxes(ident string) (*Box, error) {
boxlock.Lock()
b, ok := boxofboxes[ident]
boxlock.Unlock()
if ok {
return b, nil
}
boxinglock.Lock()
defer boxinglock.Unlock()
boxlock.Lock()
b, ok = boxofboxes[ident]
boxlock.Unlock()
if ok {
return b, nil
}
var info string var info string
row := stmtGetXonker.QueryRow(ident, "boxes") row := stmtGetXonker.QueryRow(ident, "boxes")
err := row.Scan(&info) err := row.Scan(&info)
if err != nil { if err == nil {
m := strings.Split(info, " ")
b := &Box{In: m[0], Out: m[1], Shared: m[2]}
return b, true
}
j, err := GetJunk(ident) j, err := GetJunk(ident)
if err != nil { if err != nil {
return nil, err log.Printf("error getting boxes: %s", err)
return nil, false
} }
inbox, _ := j.GetString("inbox") inbox, _ := j.GetString("inbox")
outbox, _ := j.GetString("outbox") outbox, _ := j.GetString("outbox")
sbox, _ := j.FindString([]string{"endpoints", "sharedInbox"}) sbox, _ := j.FindString([]string{"endpoints", "sharedInbox"})
b = &Box{In: inbox, Out: outbox, Shared: sbox} b := &Box{In: inbox, Out: outbox, Shared: sbox}
if inbox != "" { if inbox != "" {
m := strings.Join([]string{inbox, outbox, sbox}, " ") m := strings.Join([]string{inbox, outbox, sbox}, " ")
_, err = stmtSaveXonker.Exec(ident, m, "boxes") _, err = stmtSaveXonker.Exec(ident, m, "boxes")
@ -298,16 +281,8 @@ func getboxes(ident string) (*Box, error) {
log.Printf("error saving boxes: %s", err) log.Printf("error saving boxes: %s", err)
} }
} }
} else { return b, true
m := strings.Split(info, " ") }})
b = &Box{In: m[0], Out: m[1], Shared: m[2]}
}
boxlock.Lock()
boxofboxes[ident] = b
boxlock.Unlock()
return b, nil
}
func gimmexonks(user *WhatAbout, outbox string) { func gimmexonks(user *WhatAbout, outbox string) {
log.Printf("getting outbox: %s", outbox) log.Printf("getting outbox: %s", outbox)
@ -358,9 +333,10 @@ func peeppeep() {
continue continue
} }
log.Printf("getting updates: %s", f.XID) log.Printf("getting updates: %s", f.XID)
box, err := getboxes(f.XID) var box *Box
if err != nil { ok := boxofboxes.Get(f.XID, &box)
log.Printf("error getting outbox: %s", err) if !ok {
log.Printf("error getting outbox")
continue continue
} }
gimmexonks(user, box.Out) gimmexonks(user, box.Out)
@ -1137,8 +1113,9 @@ func honkworldwide(user *WhatAbout, honk *Honk) {
if a == thewholeworld || a == user.URL || strings.HasSuffix(a, "/followers") { if a == thewholeworld || a == user.URL || strings.HasSuffix(a, "/followers") {
continue continue
} }
box, _ := getboxes(a) var box *Box
if box != nil && honk.Public && box.Shared != "" { ok := boxofboxes.Get(a, &box)
if ok && honk.Public && box.Shared != "" {
rcpts["%"+box.Shared] = true rcpts["%"+box.Shared] = true
} else { } else {
rcpts[a] = true rcpts[a] = true
@ -1149,8 +1126,9 @@ func honkworldwide(user *WhatAbout, honk *Honk) {
if f.XID == user.URL { if f.XID == user.URL {
continue continue
} }
box, _ := getboxes(f.XID) var box *Box
if box != nil && box.Shared != "" { ok := boxofboxes.Get(f.XID, &box)
if ok && box.Shared != "" {
rcpts["%"+box.Shared] = true rcpts["%"+box.Shared] = true
} else { } else {
rcpts[f.XID] = true rcpts[f.XID] = true
@ -1191,41 +1169,23 @@ func asjonker(user *WhatAbout) junk.Junk {
return j return j
} }
var handfull = make(map[string]string) var handfull = cacheNew(cacheOptions{Filler: func(name string) (string, bool) {
var handlock sync.Mutex
func gofish(name string) string {
if name[0] == '@' {
name = name[1:]
}
m := strings.Split(name, "@") m := strings.Split(name, "@")
if len(m) != 2 { if len(m) != 2 {
log.Printf("bad fish name: %s", name) log.Printf("bad fish name: %s", name)
return "" return "", true
}
handlock.Lock()
ref, ok := handfull[name]
handlock.Unlock()
if ok {
return ref
} }
row := stmtGetXonker.QueryRow(name, "fishname") row := stmtGetXonker.QueryRow(name, "fishname")
var href string var href string
err := row.Scan(&href) err := row.Scan(&href)
if err == nil { if err == nil {
handlock.Lock() return href, true
handfull[name] = href
handlock.Unlock()
return href
} }
log.Printf("fishing for %s", name) log.Printf("fishing for %s", name)
j, err := GetJunkFast(fmt.Sprintf("https://%s/.well-known/webfinger?resource=acct:%s", m[1], name)) j, err := GetJunkFast(fmt.Sprintf("https://%s/.well-known/webfinger?resource=acct:%s", m[1], name))
if err != nil { if err != nil {
log.Printf("failed to go fish %s: %s", name, err) log.Printf("failed to go fish %s: %s", name, err)
handlock.Lock() return "", true
handfull[name] = ""
handlock.Unlock()
return ""
} }
links, _ := j.GetArray("links") links, _ := j.GetArray("links")
for _, li := range links { for _, li := range links {
@ -1241,17 +1201,20 @@ func gofish(name string) string {
if err != nil { if err != nil {
log.Printf("error saving fishname: %s", err) log.Printf("error saving fishname: %s", err)
} }
handlock.Lock() return href, true
handfull[name] = href }
handlock.Unlock() }
return href, true
}})
func gofish(name string) string {
if name[0] == '@' {
name = name[1:]
}
var href string
handfull.Get(name, &href)
return href return href
} }
}
handlock.Lock()
handfull[name] = ""
handlock.Unlock()
return ""
}
func isactor(t string) bool { func isactor(t string) bool {
switch t { switch t {

View File

@ -22,15 +22,20 @@ import (
type cacheFiller func(key interface{}) (interface{}, bool) type cacheFiller func(key interface{}) (interface{}, bool)
type cacheOptions struct {
Filler interface{}
}
type Cache struct { type Cache struct {
cache map[interface{}]interface{} cache map[interface{}]interface{}
filler cacheFiller filler cacheFiller
lock sync.Mutex lock sync.Mutex
} }
func cacheNew(fillfn interface{}) *Cache { func cacheNew(options cacheOptions) *Cache {
c := new(Cache) c := new(Cache)
c.cache = make(map[interface{}]interface{}) c.cache = make(map[interface{}]interface{})
fillfn := options.Filler
ftype := reflect.TypeOf(fillfn) ftype := reflect.TypeOf(fillfn)
if ftype.Kind() != reflect.Func { if ftype.Kind() != reflect.Func {
panic("cache filler is not function") panic("cache filler is not function")

View File

@ -91,9 +91,10 @@ func deliverate(goarounds int, username string, rcpt string, msg []byte) {
if rcpt[0] == '%' { if rcpt[0] == '%' {
inbox = rcpt[1:] inbox = rcpt[1:]
} else { } else {
box, err := getboxes(rcpt) var box *Box
if err != nil { ok := boxofboxes.Get(rcpt, &box)
log.Printf("error getting inbox %s: %s", rcpt, err) if !ok {
log.Printf("failed getting inbox for %s", rcpt)
sayitagain(goarounds+1, username, rcpt, msg) sayitagain(goarounds+1, username, rcpt, msg)
return return
} }

View File

@ -63,7 +63,7 @@ func (ft filtType) String() string {
type afiltermap map[filtType][]*Filter type afiltermap map[filtType][]*Filter
var filtcache = cacheNew(func(userid int64) (afiltermap, bool) { var filtcache = cacheNew(cacheOptions{Filler: func(userid int64) (afiltermap, bool) {
rows, err := stmtGetFilters.Query(userid) rows, err := stmtGetFilters.Query(userid)
if err != nil { if err != nil {
log.Printf("error querying filters: %s", err) log.Printf("error querying filters: %s", err)
@ -126,7 +126,7 @@ var filtcache = cacheNew(func(userid int64) (afiltermap, bool) {
return sorting[i].Name < sorting[j].Name return sorting[i].Name < sorting[j].Name
}) })
return filtmap, true return filtmap, true
}) }})
func getfilters(userid int64, scope filtType) []*Filter { func getfilters(userid int64, scope filtType) []*Filter {
var filtmap afiltermap var filtmap afiltermap

22
web.go
View File

@ -219,9 +219,10 @@ func crappola(j junk.Junk) bool {
} }
func ping(user *WhatAbout, who string) { func ping(user *WhatAbout, who string) {
box, err := getboxes(who) var box *Box
if err != nil { ok := boxofboxes.Get(who, &box)
log.Printf("no inbox for ping: %s", err) if !ok {
log.Printf("no inbox to ping %s", who)
return return
} }
j := junk.New() j := junk.New()
@ -231,7 +232,7 @@ func ping(user *WhatAbout, who string) {
j["actor"] = user.URL j["actor"] = user.URL
j["to"] = who j["to"] = who
keyname, key := ziggy(user.Name) keyname, key := ziggy(user.Name)
err = PostJunk(keyname, key, box.In, j) err := PostJunk(keyname, key, box.In, j)
if err != nil { if err != nil {
log.Printf("can't send ping: %s", err) log.Printf("can't send ping: %s", err)
return return
@ -240,9 +241,10 @@ func ping(user *WhatAbout, who string) {
} }
func pong(user *WhatAbout, who string, obj string) { func pong(user *WhatAbout, who string, obj string) {
box, err := getboxes(who) var box *Box
if err != nil { ok := boxofboxes.Get(who, &box)
log.Printf("no inbox for pong %s : %s", who, err) if !ok {
log.Printf("no inbox to pong %s", who)
return return
} }
j := junk.New() j := junk.New()
@ -253,7 +255,7 @@ func pong(user *WhatAbout, who string, obj string) {
j["to"] = who j["to"] = who
j["object"] = obj j["object"] = obj
keyname, key := ziggy(user.Name) keyname, key := ziggy(user.Name)
err = PostJunk(keyname, key, box.In, j) err := PostJunk(keyname, key, box.In, j)
if err != nil { if err != nil {
log.Printf("can't send pong: %s", err) log.Printf("can't send pong: %s", err)
return return
@ -1153,7 +1155,7 @@ func showhonkers(w http.ResponseWriter, r *http.Request) {
} }
} }
var combocache = cacheNew(func(userid int64) ([]string, bool) { var combocache = cacheNew(cacheOptions{Filler: func(userid int64) ([]string, bool) {
honkers := gethonkers(userid) honkers := gethonkers(userid)
var combos []string var combos []string
for _, h := range honkers { for _, h := range honkers {
@ -1167,7 +1169,7 @@ var combocache = cacheNew(func(userid int64) ([]string, bool) {
combos = oneofakind(combos) combos = oneofakind(combos)
sort.Strings(combos) sort.Strings(combos)
return combos, true return combos, true
}) }})
func showcombos(w http.ResponseWriter, r *http.Request) { func showcombos(w http.ResponseWriter, r *http.Request) {
userinfo := login.GetUserInfo(r) userinfo := login.GetUserInfo(r)