Notmuch: be resilient to config errors

Right now notmuch panics if something goes wrong in the configure event.
This patch checks for that and returns an error instead, so that we can at least
get the UI up and running (and all the other accounts)

The experience will be completely degraded until another configure event occurs.
This commit is contained in:
Reto Brunner 2019-10-28 21:31:01 +01:00 committed by Drew DeVault
parent cd39e8f90c
commit 6dc537fbe3

View file

@ -32,6 +32,7 @@ type worker struct {
uidStore *uidstore.Store uidStore *uidstore.Store
nameQueryMap map[string]string nameQueryMap map[string]string
db *notmuch.DB db *notmuch.DB
setupErr error
currentSortCriteria []*types.SortCriterion currentSortCriteria []*types.SortCriterion
} }
@ -69,6 +70,14 @@ func (w *worker) err(msg types.WorkerMessage, err error) {
}, nil) }, nil)
} }
func (w *worker) handleMessage(msg types.WorkerMessage) error { func (w *worker) handleMessage(msg types.WorkerMessage) error {
if w.setupErr != nil {
// only configure can recover from a config error, bail for everything else
_, isConfigure := msg.(*types.Configure)
if !isConfigure {
return w.setupErr
}
}
switch msg := msg.(type) { switch msg := msg.(type) {
case *types.Unsupported: case *types.Unsupported:
// No-op // No-op
@ -109,6 +118,15 @@ func (w *worker) handleMessage(msg types.WorkerMessage) error {
} }
func (w *worker) handleConfigure(msg *types.Configure) error { func (w *worker) handleConfigure(msg *types.Configure) error {
var err error
defer func() {
if err == nil {
w.setupErr = nil
return
}
w.setupErr = fmt.Errorf("notmuch: %v", err)
}()
u, err := url.Parse(msg.Config.Source) u, err := url.Parse(msg.Config.Source)
if err != nil { if err != nil {
w.w.Logger.Printf("error configuring notmuch worker: %v", err) w.w.Logger.Printf("error configuring notmuch worker: %v", err)
@ -120,8 +138,9 @@ func (w *worker) handleConfigure(msg *types.Configure) error {
} }
pathToDB := filepath.Join(home, u.Path) pathToDB := filepath.Join(home, u.Path)
w.uidStore = uidstore.NewStore() w.uidStore = uidstore.NewStore()
if err = w.loadQueryMap(msg.Config); err != nil { err = w.loadQueryMap(msg.Config)
return fmt.Errorf("could not load query map: %v", err) if err != nil {
return fmt.Errorf("could not load query map configuration: %v", err)
} }
excludedTags := w.loadExcludeTags(msg.Config) excludedTags := w.loadExcludeTags(msg.Config)
w.db = notmuch.NewDB(pathToDB, excludedTags, w.w.Logger) w.db = notmuch.NewDB(pathToDB, excludedTags, w.w.Logger)
@ -393,7 +412,7 @@ func (w *worker) loadQueryMap(acctConfig *config.AccountConfig) error {
split := strings.SplitN(line, "=", 2) split := strings.SplitN(line, "=", 2)
if len(split) != 2 { if len(split) != 2 {
return fmt.Errorf("invalid line %q, want name=query", line) return fmt.Errorf("%v: invalid line %q, want name=query", file, line)
} }
w.nameQueryMap[split[0]] = split[1] w.nameQueryMap[split[0]] = split[1]
} }