the spice must flow. redeliverate with extreme prejudice.

This commit is contained in:
Ted Unangst 2019-04-14 21:35:42 -04:00
parent 4e223b7922
commit bf323bd0e5
6 changed files with 90 additions and 8 deletions

6
README
View File

@ -54,3 +54,9 @@ Then run honk.
Refer also to the docs directory, in particular manual.txt.
Busy honk instances may use megabytes of memory.
-- upgrade
./honk upgrade
./honk

View File

@ -21,6 +21,11 @@ import (
"time"
)
type Doover struct {
ID int64
When time.Time
}
func sayitagain(goarounds int, username string, rcpt string, msg []byte) {
var drift time.Duration
switch goarounds {
@ -36,9 +41,13 @@ func sayitagain(goarounds int, username string, rcpt string, msg []byte) {
log.Printf("he's dead jim: %s", rcpt)
return
}
drift += time.Duration(rand.Int63n(int64(drift / 16)))
drift += time.Duration(rand.Int63n(int64(drift / 10)))
when := time.Now().UTC().Add(drift)
log.Print(when.Format(dbtimeformat), goarounds, username, rcpt, msg)
stmtAddDoover.Exec(when.Format(dbtimeformat), goarounds, username, rcpt, msg)
select {
case pokechan <- 0:
default:
}
}
func deliverate(goarounds int, username string, rcpt string, msg []byte) {
@ -53,5 +62,56 @@ func deliverate(goarounds int, username string, rcpt string, msg []byte) {
if err != nil {
log.Printf("failed to post json to %s: %s", inbox, err)
sayitagain(goarounds+1, username, rcpt, msg)
return
}
}
var pokechan = make(chan int)
func redeliverator() {
sleeper := time.NewTimer(0)
for {
select {
case <-pokechan:
if !sleeper.Stop() {
<-sleeper.C
}
time.Sleep(1 * time.Minute)
case <-sleeper.C:
}
rows, err := stmtGetDoovers.Query()
if err != nil {
log.Printf("wat?")
time.Sleep(1 * time.Minute)
continue
}
var doovers []Doover
for rows.Next() {
var d Doover
var dt string
rows.Scan(&d.ID, &dt)
d.When, _ = time.Parse(dbtimeformat, dt)
doovers = append(doovers, d)
}
rows.Close()
now := time.Now().UTC()
nexttime := now.Add(24 * time.Hour)
for _, d := range doovers {
if d.When.Before(now) {
var goarounds int
var username, rcpt string
var msg []byte
row := stmtLoadDoover.QueryRow(d.ID)
row.Scan(&goarounds, &username, &rcpt, &msg)
stmtZapDoover.Exec(d.ID)
log.Printf("redeliverating %s try %d", rcpt, goarounds)
deliverate(goarounds, username, rcpt, msg)
} else if d.When.Before(nexttime) {
nexttime = d.When
}
}
dur := nexttime.Sub(now).Round(time.Second) + 1*time.Minute
sleeper.Reset(dur)
}
}

View File

@ -914,6 +914,8 @@ func serve() {
if err != nil {
log.Fatal(err)
}
go redeliverator()
debug := false
getconfig("debug", &debug)
readviews = ParseTemplates(debug,
@ -975,6 +977,7 @@ var stmtHonkers, stmtDubbers, stmtOneXonk, stmtHonks, stmtUserHonks *sql.Stmt
var stmtHonksForUser, stmtDeleteHonk, stmtSaveDub *sql.Stmt
var stmtHonksByHonker, stmtSaveHonk, stmtFileData, stmtWhatAbout *sql.Stmt
var stmtFindXonk, stmtSaveDonk, stmtFindFile, stmtSaveFile *sql.Stmt
var stmtAddDoover, stmtGetDoovers, stmtLoadDoover, stmtZapDoover *sql.Stmt
func preparetodie(db *sql.DB, s string) *sql.Stmt {
stmt, err := db.Prepare(s)
@ -1001,6 +1004,10 @@ func prepareStatements(db *sql.DB) {
stmtSaveFile = preparetodie(db, "insert into files (xid, name, url, media, content) values (?, ?, ?, ?, ?)")
stmtWhatAbout = preparetodie(db, "select userid, username, displayname, about, pubkey from users where username = ?")
stmtSaveDub = preparetodie(db, "insert into honkers (userid, name, xid, flavor) values (?, ?, ?, ?)")
stmtAddDoover = preparetodie(db, "insert into doovers (dt, tries, username, rcpt, msg) values (?, ?, ?, ?, ?)")
stmtGetDoovers = preparetodie(db, "select dooverid, dt from doovers")
stmtLoadDoover = preparetodie(db, "select tries, username, rcpt, msg from doovers where dooverid = ?")
stmtZapDoover = preparetodie(db, "delete from doovers where dooverid = ?")
}
func ElaborateUnitTests() {

View File

@ -3,6 +3,7 @@ CREATE TABLE honks (honkid integer primary key, userid integer, what text, honke
CREATE TABLE donks (honkid integer, fileid integer);
CREATE TABLE files(fileid integer primary key, xid text, name text, url text, media text, content blob);
CREATE TABLE honkers (honkerid integer primary key, userid integer, name text, xid text, flavor text, pubkey text);
create table doovers(dooverid integer primary key, dt text, tries integer, username text, rcpt text, msg blob);
create index idx_honksxid on honks(xid);
create index idx_honkshonker on honks(honker);

View File

@ -16,24 +16,32 @@
package main
import (
"database/sql"
"log"
"os"
)
func doordie(db *sql.DB, s string) {
_, err := db.Exec(s)
if err != nil {
log.Fatal(err)
}
}
func upgradedb() {
db := opendatabase()
dbversion := 0
getconfig("dbversion", &dbversion)
var err error
switch dbversion {
case 0:
_, err = db.Exec("insert into config (key, value) values ('dbversion', 1)")
if err != nil {
log.Fatal(err)
}
doordie(db, "insert into config (key, value) values ('dbversion', 1)")
fallthrough
case 1:
doordie(db, "create table doovers(dooverid integer primary key, dt text, tries integer, username text, rcpt text, msg blob)")
doordie(db, "update config set value = 2 where key = 'dbversion'")
fallthrough
case 2:
default:
log.Fatalf("can't upgrade unknown version %d", dbversion)
}

View File

@ -70,7 +70,7 @@ var dbtimeformat = "2006-01-02 15:04:05"
var alreadyopendb *sql.DB
var dbname = "honk.db"
var stmtConfig *sql.Stmt
var myVersion = 1
var myVersion = 2
func initdb() {
schema, err := ioutil.ReadFile("schema.sql")