From 8a6eaf5fe1b3bd366ce1bba8e4b145b4dd11b8d7 Mon Sep 17 00:00:00 2001 From: Ted Unangst Date: Sat, 9 Nov 2019 02:15:15 -0500 Subject: [PATCH] move the memory intensive and sometimes fragile image code to a special backend process --- activity.go | 4 +-- backend.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++ honk.go | 2 ++ web.go | 4 +-- 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 backend.go diff --git a/activity.go b/activity.go index 4094bdc..31f91f1 100644 --- a/activity.go +++ b/activity.go @@ -34,7 +34,6 @@ import ( "humungus.tedunangst.com/r/webs/cache" "humungus.tedunangst.com/r/webs/gate" "humungus.tedunangst.com/r/webs/httpsig" - "humungus.tedunangst.com/r/webs/image" "humungus.tedunangst.com/r/webs/junk" ) @@ -175,8 +174,7 @@ func savedonk(url string, name, desc, media string, localize bool) *Donk { log.Printf("truncation likely") } if strings.HasPrefix(media, "image") { - img, err := image.Vacuum(&buf, - image.Params{LimitSize: 4200 * 4200, MaxWidth: 2048, MaxHeight: 2048}) + img, err := shrinkit(data) if err != nil { log.Printf("unable to decode image: %s", err) localize = false diff --git a/backend.go b/backend.go new file mode 100644 index 0000000..b101ccc --- /dev/null +++ b/backend.go @@ -0,0 +1,101 @@ +// +// Copyright (c) 2019 Ted Unangst +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +package main + +import ( + "bytes" + "log" + "net" + "net/rpc" + "os" + "os/exec" + + "humungus.tedunangst.com/r/webs/image" +) + +type Shrinker struct { +} + +type ShrinkerArgs struct { + Buf []byte + Params image.Params +} + +type ShrinkerResult struct { + Image *image.Image +} + +func (s *Shrinker) Shrink(args *ShrinkerArgs, res *ShrinkerResult) error { + img, err := image.Vacuum(bytes.NewReader(args.Buf), args.Params) + if err != nil { + return err + } + res.Image = img + return nil +} + +func backendSockname() string { + return dataDir + "/backend.sock" +} + +func shrinkit(data []byte) (*image.Image, error) { + cl, err := rpc.Dial("unix", backendSockname()) + if err != nil { + return nil, err + } + defer cl.Close() + var res ShrinkerResult + err = cl.Call("Shrinker.Shrink", &ShrinkerArgs{ + Buf: data, + Params: image.Params{LimitSize: 4200 * 4200, MaxWidth: 2048, MaxHeight: 2048}, + }, &res) + if err != nil { + return nil, err + } + return res.Image, nil +} + +func backendServer() { + log.Printf("backend server running") + shrinker := new(Shrinker) + srv := rpc.NewServer() + err := srv.Register(shrinker) + if err != nil { + log.Panicf("unable to register shrinker: %s", err) + } + + sockname := backendSockname() + err = os.Remove(sockname) + if err != nil && !os.IsNotExist(err) { + log.Panicf("unable to unlink socket: %s", err) + } + + lis, err := net.Listen("unix", sockname) + if err != nil { + log.Panicf("unable to register shrinker: %s", err) + } + srv.Accept(lis) +} + +func startBackendServer() { + proc := exec.Command(os.Args[0], "-datadir", dataDir, "backend") + proc.Stdout = os.Stdout + proc.Stderr = os.Stderr + err := proc.Start() + if err != nil { + log.Panicf("can't exec backend: %s", err) + } +} diff --git a/honk.go b/honk.go index 5ccfcbb..d76799d 100644 --- a/honk.go +++ b/honk.go @@ -269,6 +269,8 @@ func main() { ping(user, targ) case "run": serve() + case "backend": + backendServer() case "test": ElaborateUnitTests() default: diff --git a/web.go b/web.go index 6824a7c..7a62fdf 100644 --- a/web.go +++ b/web.go @@ -36,7 +36,6 @@ import ( "github.com/gorilla/mux" "humungus.tedunangst.com/r/webs/cache" "humungus.tedunangst.com/r/webs/httpsig" - "humungus.tedunangst.com/r/webs/image" "humungus.tedunangst.com/r/webs/junk" "humungus.tedunangst.com/r/webs/login" "humungus.tedunangst.com/r/webs/rss" @@ -1399,7 +1398,7 @@ func submithonk(w http.ResponseWriter, r *http.Request) { data := buf.Bytes() xid := xfiltrate() var media, name string - img, err := image.Vacuum(&buf, image.Params{MaxWidth: 2048, MaxHeight: 2048}) + img, err := shrinkit(data) if err == nil { data = img.Data format := img.Format @@ -2060,6 +2059,7 @@ func serve() { if err != nil { log.Fatal(err) } + startBackendServer() go enditall() go redeliverator() go tracker()