github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/23_proto_actor/cluster-broadcast/shared/protos_protoactor.go (about)

     1  package shared
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"math"
     8  	"time"
     9  
    10  	"github.com/AsynkronIT/protoactor-go/actor"
    11  	"github.com/AsynkronIT/protoactor-go/cluster"
    12  	"github.com/AsynkronIT/protoactor-go/remote"
    13  	"github.com/gogo/protobuf/proto"
    14  )
    15  
    16  var _ = proto.Marshal
    17  var _ = fmt.Errorf
    18  var _ = math.Inf
    19  
    20  var rootContext = actor.EmptyRootContext
    21  
    22  var xCalculatorFactory func() Calculator
    23  
    24  // CalculatorFactory produces a Calculator
    25  func CalculatorFactory(factory func() Calculator) {
    26  	xCalculatorFactory = factory
    27  }
    28  
    29  // GetCalculatorGrain instantiates a new CalculatorGrain with given ID
    30  func GetCalculatorGrain(id string) *CalculatorGrain {
    31  	return &CalculatorGrain{ID: id}
    32  }
    33  
    34  // Calculator interfaces the services available to the Calculator
    35  type Calculator interface {
    36  	Init(id string)
    37  	Terminate()
    38  
    39  	Add(*NumberRequest, cluster.GrainContext) (*CountResponse, error)
    40  
    41  	Subtract(*NumberRequest, cluster.GrainContext) (*CountResponse, error)
    42  
    43  	GetCurrent(*Noop, cluster.GrainContext) (*CountResponse, error)
    44  }
    45  
    46  // CalculatorGrain holds the base data for the CalculatorGrain
    47  type CalculatorGrain struct {
    48  	ID string
    49  }
    50  
    51  // Add requests the execution on to the cluster using default options
    52  func (g *CalculatorGrain) Add(r *NumberRequest) (*CountResponse, error) {
    53  	return g.AddWithOpts(r, cluster.DefaultGrainCallOptions())
    54  }
    55  
    56  // AddWithOpts requests the execution on to the cluster
    57  func (g *CalculatorGrain) AddWithOpts(r *NumberRequest, opts *cluster.GrainCallOptions) (*CountResponse, error) {
    58  	fun := func() (*CountResponse, error) {
    59  		pid, statusCode := cluster.Get(g.ID, "Calculator")
    60  		if statusCode != remote.ResponseStatusCodeOK {
    61  			return nil, fmt.Errorf("get PID failed with StatusCode: %v", statusCode)
    62  		}
    63  		bytes, err := proto.Marshal(r)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		request := &cluster.GrainRequest{MethodIndex: 0, MessageData: bytes}
    68  		response, err := rootContext.RequestFuture(pid, request, opts.Timeout).Result()
    69  		if err != nil {
    70  			return nil, err
    71  		}
    72  		switch msg := response.(type) {
    73  		case *cluster.GrainResponse:
    74  			result := &CountResponse{}
    75  			err = proto.Unmarshal(msg.MessageData, result)
    76  			if err != nil {
    77  				return nil, err
    78  			}
    79  			return result, nil
    80  		case *cluster.GrainErrorResponse:
    81  			return nil, errors.New(msg.Err)
    82  		default:
    83  			return nil, errors.New("unknown response")
    84  		}
    85  	}
    86  
    87  	var res *CountResponse
    88  	var err error
    89  	for i := 0; i < opts.RetryCount; i++ {
    90  		res, err = fun()
    91  		if err == nil || err.Error() != "future: timeout" {
    92  			return res, err
    93  		} else if opts.RetryAction != nil {
    94  			opts.RetryAction(i)
    95  		}
    96  	}
    97  	return nil, err
    98  }
    99  
   100  // AddChan allows to use a channel to execute the method using default options
   101  func (g *CalculatorGrain) AddChan(r *NumberRequest) (<-chan *CountResponse, <-chan error) {
   102  	return g.AddChanWithOpts(r, cluster.DefaultGrainCallOptions())
   103  }
   104  
   105  // AddChanWithOpts allows to use a channel to execute the method
   106  func (g *CalculatorGrain) AddChanWithOpts(r *NumberRequest, opts *cluster.GrainCallOptions) (<-chan *CountResponse, <-chan error) {
   107  	c := make(chan *CountResponse)
   108  	e := make(chan error)
   109  	go func() {
   110  		res, err := g.AddWithOpts(r, opts)
   111  		if err != nil {
   112  			e <- err
   113  		} else {
   114  			c <- res
   115  		}
   116  		close(c)
   117  		close(e)
   118  	}()
   119  	return c, e
   120  }
   121  
   122  // Subtract requests the execution on to the cluster using default options
   123  func (g *CalculatorGrain) Subtract(r *NumberRequest) (*CountResponse, error) {
   124  	return g.SubtractWithOpts(r, cluster.DefaultGrainCallOptions())
   125  }
   126  
   127  // SubtractWithOpts requests the execution on to the cluster
   128  func (g *CalculatorGrain) SubtractWithOpts(r *NumberRequest, opts *cluster.GrainCallOptions) (*CountResponse, error) {
   129  	fun := func() (*CountResponse, error) {
   130  		pid, statusCode := cluster.Get(g.ID, "Calculator")
   131  		if statusCode != remote.ResponseStatusCodeOK {
   132  			return nil, fmt.Errorf("get PID failed with StatusCode: %v", statusCode)
   133  		}
   134  		bytes, err := proto.Marshal(r)
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  		request := &cluster.GrainRequest{MethodIndex: 1, MessageData: bytes}
   139  		response, err := rootContext.RequestFuture(pid, request, opts.Timeout).Result()
   140  		if err != nil {
   141  			return nil, err
   142  		}
   143  		switch msg := response.(type) {
   144  		case *cluster.GrainResponse:
   145  			result := &CountResponse{}
   146  			err = proto.Unmarshal(msg.MessageData, result)
   147  			if err != nil {
   148  				return nil, err
   149  			}
   150  			return result, nil
   151  		case *cluster.GrainErrorResponse:
   152  			return nil, errors.New(msg.Err)
   153  		default:
   154  			return nil, errors.New("unknown response")
   155  		}
   156  	}
   157  
   158  	var res *CountResponse
   159  	var err error
   160  	for i := 0; i < opts.RetryCount; i++ {
   161  		res, err = fun()
   162  		if err == nil || err.Error() != "future: timeout" {
   163  			return res, err
   164  		} else if opts.RetryAction != nil {
   165  			opts.RetryAction(i)
   166  		}
   167  	}
   168  	return nil, err
   169  }
   170  
   171  // SubtractChan allows to use a channel to execute the method using default options
   172  func (g *CalculatorGrain) SubtractChan(r *NumberRequest) (<-chan *CountResponse, <-chan error) {
   173  	return g.SubtractChanWithOpts(r, cluster.DefaultGrainCallOptions())
   174  }
   175  
   176  // SubtractChanWithOpts allows to use a channel to execute the method
   177  func (g *CalculatorGrain) SubtractChanWithOpts(r *NumberRequest, opts *cluster.GrainCallOptions) (<-chan *CountResponse, <-chan error) {
   178  	c := make(chan *CountResponse)
   179  	e := make(chan error)
   180  	go func() {
   181  		res, err := g.SubtractWithOpts(r, opts)
   182  		if err != nil {
   183  			e <- err
   184  		} else {
   185  			c <- res
   186  		}
   187  		close(c)
   188  		close(e)
   189  	}()
   190  	return c, e
   191  }
   192  
   193  // GetCurrent requests the execution on to the cluster using default options
   194  func (g *CalculatorGrain) GetCurrent(r *Noop) (*CountResponse, error) {
   195  	return g.GetCurrentWithOpts(r, cluster.DefaultGrainCallOptions())
   196  }
   197  
   198  // GetCurrentWithOpts requests the execution on to the cluster
   199  func (g *CalculatorGrain) GetCurrentWithOpts(r *Noop, opts *cluster.GrainCallOptions) (*CountResponse, error) {
   200  	fun := func() (*CountResponse, error) {
   201  		pid, statusCode := cluster.Get(g.ID, "Calculator")
   202  		if statusCode != remote.ResponseStatusCodeOK {
   203  			return nil, fmt.Errorf("get PID failed with StatusCode: %v", statusCode)
   204  		}
   205  		bytes, err := proto.Marshal(r)
   206  		if err != nil {
   207  			return nil, err
   208  		}
   209  		request := &cluster.GrainRequest{MethodIndex: 2, MessageData: bytes}
   210  		response, err := rootContext.RequestFuture(pid, request, opts.Timeout).Result()
   211  		if err != nil {
   212  			return nil, err
   213  		}
   214  		switch msg := response.(type) {
   215  		case *cluster.GrainResponse:
   216  			result := &CountResponse{}
   217  			err = proto.Unmarshal(msg.MessageData, result)
   218  			if err != nil {
   219  				return nil, err
   220  			}
   221  			return result, nil
   222  		case *cluster.GrainErrorResponse:
   223  			return nil, errors.New(msg.Err)
   224  		default:
   225  			return nil, errors.New("unknown response")
   226  		}
   227  	}
   228  
   229  	var res *CountResponse
   230  	var err error
   231  	for i := 0; i < opts.RetryCount; i++ {
   232  		res, err = fun()
   233  		if err == nil || err.Error() != "future: timeout" {
   234  			return res, err
   235  		} else if opts.RetryAction != nil {
   236  			opts.RetryAction(i)
   237  		}
   238  	}
   239  	return nil, err
   240  }
   241  
   242  // GetCurrentChan allows to use a channel to execute the method using default options
   243  func (g *CalculatorGrain) GetCurrentChan(r *Noop) (<-chan *CountResponse, <-chan error) {
   244  	return g.GetCurrentChanWithOpts(r, cluster.DefaultGrainCallOptions())
   245  }
   246  
   247  // GetCurrentChanWithOpts allows to use a channel to execute the method
   248  func (g *CalculatorGrain) GetCurrentChanWithOpts(r *Noop, opts *cluster.GrainCallOptions) (<-chan *CountResponse, <-chan error) {
   249  	c := make(chan *CountResponse)
   250  	e := make(chan error)
   251  	go func() {
   252  		res, err := g.GetCurrentWithOpts(r, opts)
   253  		if err != nil {
   254  			e <- err
   255  		} else {
   256  			c <- res
   257  		}
   258  		close(c)
   259  		close(e)
   260  	}()
   261  	return c, e
   262  }
   263  
   264  // CalculatorActor represents the actor structure
   265  type CalculatorActor struct {
   266  	inner   Calculator
   267  	Timeout *time.Duration
   268  }
   269  
   270  // Receive ensures the lifecycle of the actor for the received message
   271  func (a *CalculatorActor) Receive(ctx actor.Context) {
   272  	switch msg := ctx.Message().(type) {
   273  	case *actor.Started:
   274  		a.inner = xCalculatorFactory()
   275  		id := ctx.Self().Id
   276  		a.inner.Init(id[7:]) // skip "remote$"
   277  		if a.Timeout != nil {
   278  			ctx.SetReceiveTimeout(*a.Timeout)
   279  		}
   280  	case *actor.ReceiveTimeout:
   281  		a.inner.Terminate()
   282  		rootContext.PoisonFuture(ctx.Self()).Wait()
   283  
   284  	case actor.AutoReceiveMessage: // pass
   285  	case actor.SystemMessage: // pass
   286  
   287  	case *cluster.GrainRequest:
   288  		switch msg.MethodIndex {
   289  
   290  		case 0:
   291  			req := &NumberRequest{}
   292  			err := proto.Unmarshal(msg.MessageData, req)
   293  			if err != nil {
   294  				log.Fatalf("[GRAIN] proto.Unmarshal failed %v", err)
   295  			}
   296  			r0, err := a.inner.Add(req, ctx)
   297  			if err == nil {
   298  				bytes, errMarshal := proto.Marshal(r0)
   299  				if errMarshal != nil {
   300  					log.Fatalf("[GRAIN] proto.Marshal failed %v", errMarshal)
   301  				}
   302  				resp := &cluster.GrainResponse{MessageData: bytes}
   303  				ctx.Respond(resp)
   304  			} else {
   305  				resp := &cluster.GrainErrorResponse{Err: err.Error()}
   306  				ctx.Respond(resp)
   307  			}
   308  
   309  		case 1:
   310  			req := &NumberRequest{}
   311  			err := proto.Unmarshal(msg.MessageData, req)
   312  			if err != nil {
   313  				log.Fatalf("[GRAIN] proto.Unmarshal failed %v", err)
   314  			}
   315  			r0, err := a.inner.Subtract(req, ctx)
   316  			if err == nil {
   317  				bytes, errMarshal := proto.Marshal(r0)
   318  				if errMarshal != nil {
   319  					log.Fatalf("[GRAIN] proto.Marshal failed %v", errMarshal)
   320  				}
   321  				resp := &cluster.GrainResponse{MessageData: bytes}
   322  				ctx.Respond(resp)
   323  			} else {
   324  				resp := &cluster.GrainErrorResponse{Err: err.Error()}
   325  				ctx.Respond(resp)
   326  			}
   327  
   328  		case 2:
   329  			req := &Noop{}
   330  			err := proto.Unmarshal(msg.MessageData, req)
   331  			if err != nil {
   332  				log.Fatalf("[GRAIN] proto.Unmarshal failed %v", err)
   333  			}
   334  			r0, err := a.inner.GetCurrent(req, ctx)
   335  			if err == nil {
   336  				bytes, errMarshal := proto.Marshal(r0)
   337  				if errMarshal != nil {
   338  					log.Fatalf("[GRAIN] proto.Marshal failed %v", errMarshal)
   339  				}
   340  				resp := &cluster.GrainResponse{MessageData: bytes}
   341  				ctx.Respond(resp)
   342  			} else {
   343  				resp := &cluster.GrainErrorResponse{Err: err.Error()}
   344  				ctx.Respond(resp)
   345  			}
   346  
   347  		}
   348  	default:
   349  		log.Printf("Unknown message %v", msg)
   350  	}
   351  }
   352  
   353  var xTrackerFactory func() Tracker
   354  
   355  // TrackerFactory produces a Tracker
   356  func TrackerFactory(factory func() Tracker) {
   357  	xTrackerFactory = factory
   358  }
   359  
   360  // GetTrackerGrain instantiates a new TrackerGrain with given ID
   361  func GetTrackerGrain(id string) *TrackerGrain {
   362  	return &TrackerGrain{ID: id}
   363  }
   364  
   365  // Tracker interfaces the services available to the Tracker
   366  type Tracker interface {
   367  	Init(id string)
   368  	Terminate()
   369  
   370  	RegisterGrain(*RegisterMessage, cluster.GrainContext) (*Noop, error)
   371  
   372  	DeregisterGrain(*RegisterMessage, cluster.GrainContext) (*Noop, error)
   373  
   374  	BroadcastGetCounts(*Noop, cluster.GrainContext) (*TotalsResponse, error)
   375  }
   376  
   377  // TrackerGrain holds the base data for the TrackerGrain
   378  type TrackerGrain struct {
   379  	ID string
   380  }
   381  
   382  // RegisterGrain requests the execution on to the cluster using default options
   383  func (g *TrackerGrain) RegisterGrain(r *RegisterMessage) (*Noop, error) {
   384  	return g.RegisterGrainWithOpts(r, cluster.DefaultGrainCallOptions())
   385  }
   386  
   387  // RegisterGrainWithOpts requests the execution on to the cluster
   388  func (g *TrackerGrain) RegisterGrainWithOpts(r *RegisterMessage, opts *cluster.GrainCallOptions) (*Noop, error) {
   389  	fun := func() (*Noop, error) {
   390  		pid, statusCode := cluster.Get(g.ID, "Tracker")
   391  		if statusCode != remote.ResponseStatusCodeOK {
   392  			return nil, fmt.Errorf("get PID failed with StatusCode: %v", statusCode)
   393  		}
   394  		bytes, err := proto.Marshal(r)
   395  		if err != nil {
   396  			return nil, err
   397  		}
   398  		request := &cluster.GrainRequest{MethodIndex: 0, MessageData: bytes}
   399  		response, err := rootContext.RequestFuture(pid, request, opts.Timeout).Result()
   400  		if err != nil {
   401  			return nil, err
   402  		}
   403  		switch msg := response.(type) {
   404  		case *cluster.GrainResponse:
   405  			result := &Noop{}
   406  			err = proto.Unmarshal(msg.MessageData, result)
   407  			if err != nil {
   408  				return nil, err
   409  			}
   410  			return result, nil
   411  		case *cluster.GrainErrorResponse:
   412  			return nil, errors.New(msg.Err)
   413  		default:
   414  			return nil, errors.New("unknown response")
   415  		}
   416  	}
   417  
   418  	var res *Noop
   419  	var err error
   420  	for i := 0; i < opts.RetryCount; i++ {
   421  		res, err = fun()
   422  		if err == nil || err.Error() != "future: timeout" {
   423  			return res, err
   424  		} else if opts.RetryAction != nil {
   425  			opts.RetryAction(i)
   426  		}
   427  	}
   428  	return nil, err
   429  }
   430  
   431  // RegisterGrainChan allows to use a channel to execute the method using default options
   432  func (g *TrackerGrain) RegisterGrainChan(r *RegisterMessage) (<-chan *Noop, <-chan error) {
   433  	return g.RegisterGrainChanWithOpts(r, cluster.DefaultGrainCallOptions())
   434  }
   435  
   436  // RegisterGrainChanWithOpts allows to use a channel to execute the method
   437  func (g *TrackerGrain) RegisterGrainChanWithOpts(r *RegisterMessage, opts *cluster.GrainCallOptions) (<-chan *Noop, <-chan error) {
   438  	c := make(chan *Noop)
   439  	e := make(chan error)
   440  	go func() {
   441  		res, err := g.RegisterGrainWithOpts(r, opts)
   442  		if err != nil {
   443  			e <- err
   444  		} else {
   445  			c <- res
   446  		}
   447  		close(c)
   448  		close(e)
   449  	}()
   450  	return c, e
   451  }
   452  
   453  // DeregisterGrain requests the execution on to the cluster using default options
   454  func (g *TrackerGrain) DeregisterGrain(r *RegisterMessage) (*Noop, error) {
   455  	return g.DeregisterGrainWithOpts(r, cluster.DefaultGrainCallOptions())
   456  }
   457  
   458  // DeregisterGrainWithOpts requests the execution on to the cluster
   459  func (g *TrackerGrain) DeregisterGrainWithOpts(r *RegisterMessage, opts *cluster.GrainCallOptions) (*Noop, error) {
   460  	fun := func() (*Noop, error) {
   461  		pid, statusCode := cluster.Get(g.ID, "Tracker")
   462  		if statusCode != remote.ResponseStatusCodeOK {
   463  			return nil, fmt.Errorf("get PID failed with StatusCode: %v", statusCode)
   464  		}
   465  		bytes, err := proto.Marshal(r)
   466  		if err != nil {
   467  			return nil, err
   468  		}
   469  		request := &cluster.GrainRequest{MethodIndex: 1, MessageData: bytes}
   470  		response, err := rootContext.RequestFuture(pid, request, opts.Timeout).Result()
   471  		if err != nil {
   472  			return nil, err
   473  		}
   474  		switch msg := response.(type) {
   475  		case *cluster.GrainResponse:
   476  			result := &Noop{}
   477  			err = proto.Unmarshal(msg.MessageData, result)
   478  			if err != nil {
   479  				return nil, err
   480  			}
   481  			return result, nil
   482  		case *cluster.GrainErrorResponse:
   483  			return nil, errors.New(msg.Err)
   484  		default:
   485  			return nil, errors.New("unknown response")
   486  		}
   487  	}
   488  
   489  	var res *Noop
   490  	var err error
   491  	for i := 0; i < opts.RetryCount; i++ {
   492  		res, err = fun()
   493  		if err == nil || err.Error() != "future: timeout" {
   494  			return res, err
   495  		} else if opts.RetryAction != nil {
   496  			opts.RetryAction(i)
   497  		}
   498  	}
   499  	return nil, err
   500  }
   501  
   502  // DeregisterGrainChan allows to use a channel to execute the method using default options
   503  func (g *TrackerGrain) DeregisterGrainChan(r *RegisterMessage) (<-chan *Noop, <-chan error) {
   504  	return g.DeregisterGrainChanWithOpts(r, cluster.DefaultGrainCallOptions())
   505  }
   506  
   507  // DeregisterGrainChanWithOpts allows to use a channel to execute the method
   508  func (g *TrackerGrain) DeregisterGrainChanWithOpts(r *RegisterMessage, opts *cluster.GrainCallOptions) (<-chan *Noop, <-chan error) {
   509  	c := make(chan *Noop)
   510  	e := make(chan error)
   511  	go func() {
   512  		res, err := g.DeregisterGrainWithOpts(r, opts)
   513  		if err != nil {
   514  			e <- err
   515  		} else {
   516  			c <- res
   517  		}
   518  		close(c)
   519  		close(e)
   520  	}()
   521  	return c, e
   522  }
   523  
   524  // BroadcastGetCounts requests the execution on to the cluster using default options
   525  func (g *TrackerGrain) BroadcastGetCounts(r *Noop) (*TotalsResponse, error) {
   526  	return g.BroadcastGetCountsWithOpts(r, cluster.DefaultGrainCallOptions())
   527  }
   528  
   529  // BroadcastGetCountsWithOpts requests the execution on to the cluster
   530  func (g *TrackerGrain) BroadcastGetCountsWithOpts(r *Noop, opts *cluster.GrainCallOptions) (*TotalsResponse, error) {
   531  	fun := func() (*TotalsResponse, error) {
   532  		pid, statusCode := cluster.Get(g.ID, "Tracker")
   533  		if statusCode != remote.ResponseStatusCodeOK {
   534  			return nil, fmt.Errorf("get PID failed with StatusCode: %v", statusCode)
   535  		}
   536  		bytes, err := proto.Marshal(r)
   537  		if err != nil {
   538  			return nil, err
   539  		}
   540  		request := &cluster.GrainRequest{MethodIndex: 2, MessageData: bytes}
   541  		response, err := rootContext.RequestFuture(pid, request, opts.Timeout).Result()
   542  		if err != nil {
   543  			return nil, err
   544  		}
   545  		switch msg := response.(type) {
   546  		case *cluster.GrainResponse:
   547  			result := &TotalsResponse{}
   548  			err = proto.Unmarshal(msg.MessageData, result)
   549  			if err != nil {
   550  				return nil, err
   551  			}
   552  			return result, nil
   553  		case *cluster.GrainErrorResponse:
   554  			return nil, errors.New(msg.Err)
   555  		default:
   556  			return nil, errors.New("unknown response")
   557  		}
   558  	}
   559  
   560  	var res *TotalsResponse
   561  	var err error
   562  	for i := 0; i < opts.RetryCount; i++ {
   563  		res, err = fun()
   564  		if err == nil || err.Error() != "future: timeout" {
   565  			return res, err
   566  		} else if opts.RetryAction != nil {
   567  			opts.RetryAction(i)
   568  		}
   569  	}
   570  	return nil, err
   571  }
   572  
   573  // BroadcastGetCountsChan allows to use a channel to execute the method using default options
   574  func (g *TrackerGrain) BroadcastGetCountsChan(r *Noop) (<-chan *TotalsResponse, <-chan error) {
   575  	return g.BroadcastGetCountsChanWithOpts(r, cluster.DefaultGrainCallOptions())
   576  }
   577  
   578  // BroadcastGetCountsChanWithOpts allows to use a channel to execute the method
   579  func (g *TrackerGrain) BroadcastGetCountsChanWithOpts(r *Noop, opts *cluster.GrainCallOptions) (<-chan *TotalsResponse, <-chan error) {
   580  	c := make(chan *TotalsResponse)
   581  	e := make(chan error)
   582  	go func() {
   583  		res, err := g.BroadcastGetCountsWithOpts(r, opts)
   584  		if err != nil {
   585  			e <- err
   586  		} else {
   587  			c <- res
   588  		}
   589  		close(c)
   590  		close(e)
   591  	}()
   592  	return c, e
   593  }
   594  
   595  // TrackerActor represents the actor structure
   596  type TrackerActor struct {
   597  	inner   Tracker
   598  	Timeout *time.Duration
   599  }
   600  
   601  // Receive ensures the lifecycle of the actor for the received message
   602  func (a *TrackerActor) Receive(ctx actor.Context) {
   603  	switch msg := ctx.Message().(type) {
   604  	case *actor.Started:
   605  		a.inner = xTrackerFactory()
   606  		id := ctx.Self().Id
   607  		a.inner.Init(id[7:]) // skip "remote$"
   608  		if a.Timeout != nil {
   609  			ctx.SetReceiveTimeout(*a.Timeout)
   610  		}
   611  	case *actor.ReceiveTimeout:
   612  		a.inner.Terminate()
   613  		rootContext.PoisonFuture(ctx.Self()).Wait()
   614  
   615  	case actor.AutoReceiveMessage: // pass
   616  	case actor.SystemMessage: // pass
   617  
   618  	case *cluster.GrainRequest:
   619  		switch msg.MethodIndex {
   620  
   621  		case 0:
   622  			req := &RegisterMessage{}
   623  			err := proto.Unmarshal(msg.MessageData, req)
   624  			if err != nil {
   625  				log.Fatalf("[GRAIN] proto.Unmarshal failed %v", err)
   626  			}
   627  			r0, err := a.inner.RegisterGrain(req, ctx)
   628  			if err == nil {
   629  				bytes, errMarshal := proto.Marshal(r0)
   630  				if errMarshal != nil {
   631  					log.Fatalf("[GRAIN] proto.Marshal failed %v", errMarshal)
   632  				}
   633  				resp := &cluster.GrainResponse{MessageData: bytes}
   634  				ctx.Respond(resp)
   635  			} else {
   636  				resp := &cluster.GrainErrorResponse{Err: err.Error()}
   637  				ctx.Respond(resp)
   638  			}
   639  
   640  		case 1:
   641  			req := &RegisterMessage{}
   642  			err := proto.Unmarshal(msg.MessageData, req)
   643  			if err != nil {
   644  				log.Fatalf("[GRAIN] proto.Unmarshal failed %v", err)
   645  			}
   646  			r0, err := a.inner.DeregisterGrain(req, ctx)
   647  			if err == nil {
   648  				bytes, errMarshal := proto.Marshal(r0)
   649  				if errMarshal != nil {
   650  					log.Fatalf("[GRAIN] proto.Marshal failed %v", errMarshal)
   651  				}
   652  				resp := &cluster.GrainResponse{MessageData: bytes}
   653  				ctx.Respond(resp)
   654  			} else {
   655  				resp := &cluster.GrainErrorResponse{Err: err.Error()}
   656  				ctx.Respond(resp)
   657  			}
   658  
   659  		case 2:
   660  			req := &Noop{}
   661  			err := proto.Unmarshal(msg.MessageData, req)
   662  			if err != nil {
   663  				log.Fatalf("[GRAIN] proto.Unmarshal failed %v", err)
   664  			}
   665  			r0, err := a.inner.BroadcastGetCounts(req, ctx)
   666  			if err == nil {
   667  				bytes, errMarshal := proto.Marshal(r0)
   668  				if errMarshal != nil {
   669  					log.Fatalf("[GRAIN] proto.Marshal failed %v", errMarshal)
   670  				}
   671  				resp := &cluster.GrainResponse{MessageData: bytes}
   672  				ctx.Respond(resp)
   673  			} else {
   674  				resp := &cluster.GrainErrorResponse{Err: err.Error()}
   675  				ctx.Respond(resp)
   676  			}
   677  
   678  		}
   679  	default:
   680  		log.Printf("Unknown message %v", msg)
   681  	}
   682  }