func (c *AutoRestartController) Run(ctx context.Context, workers int) error {
defer c.workqueue.ShutDown()
c.logger.Info("Starting AutoRestart controller")
if !cache.WaitForCacheSync(ctx.Done(), c.gameServerSynced) {
return fmt.Errorf("failed to wait for caches to sync")
}
for i := 0; i < workers; i++ {
go c.runWorker(ctx)
}
c.logger.Info("Started workers")
<-ctx.Done()
c.logger.Info("Shutting down workers")
return nil
}
func (c *AutoRestartController) runWorker(ctx context.Context) {
for c.processNextWorkItem(ctx) {
}
}
func (c *AutoRestartController) processNextWorkItem(ctx context.Context) bool {
obj, shutdown := c.workqueue.Get()
if shutdown {
return false
}
err := func(obj interface{}) error {
defer c.workqueue.Done(obj)
key, ok := obj.(string)
if !ok {
c.workqueue.Forget(obj)
return fmt.Errorf("expected string in workqueue but got %#v", obj)
}
if err := c.syncHandler(ctx, key); err != nil {
c.workqueue.AddRateLimited(key)
return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error())
}
c.workqueue.Forget(obj)
c.logger.Infof("Successfully synced '%s'", key)
return nil
}(obj)
if err != nil {
c.logger.Error(err)
}
return true
}
func (c *AutoRestartController) syncHandler(ctx context.Context, key string) error {
namespace, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
return fmt.Errorf("invalid resource key: %s", key)
}
// Get the GameServer
gs, err := c.gameServerLister.GameServers(namespace).Get(name)
if err != nil {
if errors.IsNotFound(err) {
c.logger.Infof("GameServer %s no longer exists", key)
return nil
}
return err
}
// Only restart if still unhealthy
if gs.Status.State != agonesv1.GameServerStateUnhealthy {
c.logger.WithField("gameserver", name).Info("GameServer recovered, skipping restart")
return nil
}
// Delete the GameServer to trigger recreation by Fleet/GameServerSet
c.logger.WithField("gameserver", name).Info("Deleting unhealthy GameServer")
err = c.agonesClient.AgonesV1().GameServers(namespace).Delete(
ctx,
name,
metav1.DeleteOptions{},
)
if err != nil {
return fmt.Errorf("failed to delete GameServer: %w", err)
}
return nil
}