github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/examples/cluster/echo_service.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	"github.com/lirm/aeron-go/aeron"
     8  	"github.com/lirm/aeron-go/aeron/atomic"
     9  	"github.com/lirm/aeron-go/aeron/idlestrategy"
    10  	"github.com/lirm/aeron-go/aeron/logbuffer"
    11  	"github.com/lirm/aeron-go/cluster"
    12  	"github.com/lirm/aeron-go/cluster/codecs"
    13  )
    14  
    15  type EchoService struct {
    16  	cluster      cluster.Cluster
    17  	messageCount int32
    18  }
    19  
    20  func (s *EchoService) OnStart(cluster cluster.Cluster, image aeron.Image) {
    21  	s.cluster = cluster
    22  	if image == nil {
    23  		fmt.Printf("OnStart with no image\n")
    24  	} else {
    25  		cnt := image.Poll(func(buf *atomic.Buffer, offset int32, length int32, hdr *logbuffer.Header) {
    26  			if length == 4 && s.messageCount == 0 {
    27  				s.messageCount = buf.GetInt32(offset)
    28  			} else {
    29  				fmt.Printf("WARNING: unexpected snapshot message - pos=%d offset=%d length=%d\n",
    30  					hdr.Position(), offset, length)
    31  			}
    32  		}, 100)
    33  		fmt.Printf("OnStart with image - snapshotMsgCnt=%d messageCount=%d\n", cnt, s.messageCount)
    34  	}
    35  }
    36  
    37  func (s *EchoService) OnSessionOpen(session cluster.ClientSession, timestamp int64) {
    38  	fmt.Printf("OnSessionOpen - sessionId=%d timestamp=%v\n", session.Id(), timestamp)
    39  }
    40  
    41  func (s *EchoService) OnSessionClose(
    42  	session cluster.ClientSession,
    43  	timestamp int64,
    44  	reason codecs.CloseReasonEnum,
    45  ) {
    46  	fmt.Printf("OnSessionClose - sessionId=%d timestamp=%v reason=%v\n", session.Id(), timestamp, reason)
    47  }
    48  
    49  func (s *EchoService) OnSessionMessage(
    50  	session cluster.ClientSession,
    51  	timestamp int64,
    52  	buffer *atomic.Buffer,
    53  	offset int32,
    54  	length int32,
    55  	header *logbuffer.Header,
    56  ) {
    57  	s.messageCount++
    58  	for offerCnt := 1; ; offerCnt++ {
    59  		result := session.Offer(buffer, offset, length, nil)
    60  		if result >= 0 {
    61  			return
    62  		} else if result == aeron.BackPressured || result == aeron.AdminAction {
    63  			s.cluster.IdleStrategy().Idle(0)
    64  		} else {
    65  			fmt.Printf("WARNING: OnSessionMessage offer failed - sessionId=%d time=%d pos=%d len=%d offerCnt=%d result=%v\n",
    66  				session.Id(), timestamp, header.Position(), length, offerCnt, result)
    67  		}
    68  	}
    69  }
    70  
    71  func (s *EchoService) OnTimerEvent(correlationId, timestamp int64) {
    72  	fmt.Printf("OnTimerEvent - correlationId=%d timestamp=%v\n", correlationId, timestamp)
    73  }
    74  
    75  func (s *EchoService) OnTakeSnapshot(publication *aeron.Publication) {
    76  	fmt.Printf("OnTakeSnapshot - streamId=%d sessionId=%d messageCount=%d\n",
    77  		publication.StreamID(), publication.SessionID(), s.messageCount)
    78  	buf := atomic.MakeBuffer(make([]byte, 4))
    79  	buf.PutInt32(0, s.messageCount)
    80  	for {
    81  		result := publication.Offer(buf, 0, buf.Capacity(), nil)
    82  		if result >= 0 {
    83  			return
    84  		} else if result == aeron.BackPressured || result == aeron.AdminAction {
    85  			s.cluster.IdleStrategy().Idle(0)
    86  		} else {
    87  			fmt.Printf("WARNING: OnTakeSnapshot offer failed - result=%v\n", result)
    88  		}
    89  	}
    90  }
    91  
    92  func (s *EchoService) OnRoleChange(role cluster.Role) {
    93  	fmt.Printf("OnRoleChange - role=%v\n", role)
    94  }
    95  
    96  func (s *EchoService) OnTerminate(cluster cluster.Cluster) {
    97  	fmt.Printf("OnTerminate - role=%v logPos=%d\n", cluster.Role(), cluster.LogPosition())
    98  }
    99  
   100  func (s *EchoService) OnNewLeadershipTermEvent(
   101  	leadershipTermId int64,
   102  	logPosition int64,
   103  	timestamp int64,
   104  	termBaseLogPosition int64,
   105  	leaderMemberId int32,
   106  	logSessionId int32,
   107  	timeUnit codecs.ClusterTimeUnitEnum,
   108  	appVersion int32,
   109  ) {
   110  	fmt.Printf("OnNewLeadershipTermEvent - leaderTermId=%d logPos=%d time=%d termBase=%d leaderId=%d logSessionId=%d timeUnit=%v appVer=%d\n",
   111  		leadershipTermId, logPosition, timestamp, termBaseLogPosition, leaderMemberId, logSessionId, timeUnit, appVersion)
   112  }
   113  
   114  func main() {
   115  	ctx := aeron.NewContext()
   116  	if aeronDir := os.Getenv("AERON_DIR"); aeronDir != "" {
   117  		ctx.AeronDir(aeronDir)
   118  		fmt.Println("aeron dir: ", aeronDir)
   119  	} else if _, err := os.Stat("/dev/shm"); err == nil {
   120  		path := fmt.Sprintf("/dev/shm/aeron-%s", aeron.UserName)
   121  		ctx.AeronDir(path)
   122  		fmt.Println("aeron dir: ", path)
   123  	}
   124  
   125  	opts := cluster.NewOptions()
   126  	if idleStr := os.Getenv("NO_OP_IDLE"); idleStr != "" {
   127  		opts.IdleStrategy = &idlestrategy.Busy{}
   128  	}
   129  	if opts.ClusterDir = os.Getenv("CLUSTER_DIR"); opts.ClusterDir == "" {
   130  		opts.ClusterDir = "/tmp/aeron-go-poc/cluster"
   131  	}
   132  
   133  	service := &EchoService{}
   134  	agent, err := cluster.NewClusteredServiceAgent(ctx, opts, service)
   135  	if err != nil {
   136  		panic(err)
   137  	}
   138  
   139  	if err := agent.StartAndRun(); err != nil {
   140  		panic(err)
   141  	}
   142  }