// afterAction needs to be run after an action may have changed the current // state of the tablet. func (agent *ActionAgent) afterAction(context string, reloadSchema bool) { log.Infof("Executing post-action change callbacks") // Save the old tablet so callbacks can have a better idea of // the precise nature of the transition. oldTablet := agent.Tablet().Tablet // Actions should have side effects on the tablet, so reload the data. if err := agent.readTablet(); err != nil { log.Warningf("Failed rereading tablet after %v - services may be inconsistent: %v", context, err) } else { if updatedTablet := actor.CheckTabletMysqlPort(agent.TopoServer, agent.Mysqld, agent.Tablet()); updatedTablet != nil { agent.mutex.Lock() agent._tablet = updatedTablet agent.mutex.Unlock() } agent.runChangeCallback(oldTablet, context) } // Maybe invalidate the schema. // This adds a dependency between tabletmanager and tabletserver, // so it's not ideal. But I (alainjobart) think it's better // to have up to date schema in vtocc. if reloadSchema { tabletserver.ReloadSchema() } log.Infof("Done with post-action change callbacks") }
// StartActionLoop will start the action loop for a fake tablet, // using ft.FakeMysqlDaemon as the backing mysqld. func (ft *FakeTablet) StartActionLoop(t *testing.T, wr *wrangler.Wrangler) { if ft.Done != nil { t.Fatalf("ActionLoop for %v is already running", ft.Tablet.Alias) } ft.Done = make(chan struct{}, 1) go func() { wr.TopoServer().ActionEventLoop(ft.Tablet.Alias, func(actionPath, data string) error { actionNode, err := actionnode.ActionNodeFromJson(data, actionPath) if err != nil { t.Fatalf("ActionNodeFromJson failed: %v\n%v", err, data) } ta := actor.NewTabletActor(nil, ft.FakeMysqlDaemon, wr.TopoServer(), ft.Tablet.Alias) if err := ta.HandleAction(actionPath, actionNode.Action, actionNode.ActionGuid, false); err != nil { // action may just fail for any good reason t.Logf("HandleAction failed for %v: %v", actionNode.Action, err) } // this part would also be done by the agent tablet, err := wr.TopoServer().GetTablet(ft.Tablet.Alias) if err != nil { t.Logf("Cannot get tablet: %v", err) } else { updatedTablet := actor.CheckTabletMysqlPort(wr.TopoServer(), ft.FakeMysqlDaemon, tablet) if updatedTablet != nil { t.Logf("Updated tablet record") } } return nil }, ft.Done) }() }