github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/archive/examples/basic_replayed_subscriber/basic_replayed_subscriber.go (about) 1 // Copyright (C) 2021-2022 Talos, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // An example replayed subscriber 16 package main 17 18 import ( 19 "flag" 20 "fmt" 21 "math" 22 "time" 23 24 "github.com/lirm/aeron-go/aeron" 25 "github.com/lirm/aeron-go/aeron/atomic" 26 "github.com/lirm/aeron-go/aeron/idlestrategy" 27 "github.com/lirm/aeron-go/aeron/logbuffer" 28 "github.com/lirm/aeron-go/aeron/logging" 29 "github.com/lirm/aeron-go/archive" 30 "github.com/lirm/aeron-go/archive/examples" 31 ) 32 33 var logID = "basic_recording_subscriber" 34 var logger = logging.MustGetLogger(logID) 35 36 func main() { 37 flag.Parse() 38 39 // As per Java example 40 sampleChannel := *examples.Config.SampleChannel 41 sampleStream := int32(*examples.Config.SampleStream) 42 replayStream := sampleStream + 1 43 responseStream := sampleStream + 2 44 45 timeout := time.Duration(time.Millisecond.Nanoseconds() * *examples.Config.DriverTimeout) 46 context := aeron.NewContext() 47 context.AeronDir(*examples.Config.AeronPrefix) 48 context.MediaDriverTimeout(timeout) 49 50 options := archive.DefaultOptions() 51 options.RequestChannel = *examples.Config.RequestChannel 52 options.RequestStream = int32(*examples.Config.RequestStream) 53 options.ResponseChannel = *examples.Config.ResponseChannel 54 options.ResponseStream = responseStream 55 56 if *examples.Config.Verbose { 57 fmt.Printf("Setting loglevel: archive.DEBUG/aeron.INFO\n") 58 options.ArchiveLoglevel = logging.DEBUG 59 options.AeronLoglevel = logging.DEBUG 60 logging.SetLevel(logging.DEBUG, logID) 61 } else { 62 logging.SetLevel(logging.NOTICE, logID) 63 } 64 65 arch, err := archive.NewArchive(options, context) 66 if err != nil { 67 logger.Fatalf("Failed to connect to media driver: %s\n", err.Error()) 68 } 69 defer arch.Close() 70 71 // Enable recording events although the defaults will only log in debug mode 72 arch.EnableRecordingEvents() 73 74 recordingID, err := FindLatestRecording(arch, sampleChannel, sampleStream) 75 if err != nil { 76 logger.Fatalf(err.Error()) 77 } 78 var position int64 79 var length int64 = math.MaxInt64 80 81 logger.Infof("Start replay of channel:%s, stream:%d, position:%d, length:%d", sampleChannel, replayStream, position, length) 82 replaySessionID, err := arch.StartReplay(recordingID, position, length, sampleChannel, replayStream) 83 if err != nil { 84 logger.Fatalf(err.Error()) 85 } 86 87 // Make the channel based upon that recording and subscribe to it 88 subChannel, err := archive.AddSessionIdToChannel(sampleChannel, archive.ReplaySessionIdToStreamId(replaySessionID)) 89 if err != nil { 90 logger.Fatalf("AddReplaySessionIdToChannel() failed: %s", err.Error()) 91 } 92 93 logger.Infof("Subscribing to channel:%s, stream:%d", subChannel, replayStream) 94 subscription, err := arch.AddSubscription(subChannel, replayStream) 95 if err != nil { 96 logger.Fatal(err) 97 } 98 defer subscription.Close() 99 logger.Infof("Subscription found %v", subscription) 100 101 counter := 0 102 printHandler := func(buffer *atomic.Buffer, offset int32, length int32, header *logbuffer.Header) { 103 bytes := buffer.GetBytesArray(offset, length) 104 logger.Infof("%s", bytes) 105 counter++ 106 } 107 108 idleStrategy := idlestrategy.Sleeping{SleepFor: time.Millisecond * 1000} 109 for { 110 fragmentsRead := subscription.Poll(printHandler, 10) 111 arch.RecordingEventsPoll() 112 113 idleStrategy.Idle(fragmentsRead) 114 } 115 } 116 117 // FindLatestRecording to lookup the last recording 118 func FindLatestRecording(arch *archive.Archive, channel string, stream int32) (int64, error) { 119 descriptors, err := arch.ListRecordingsForUri(0, 100, channel, stream) 120 121 if err != nil { 122 return 0, err 123 } 124 125 if len(descriptors) == 0 { 126 return 0, fmt.Errorf("no recordings found") 127 } 128 129 descriptor := descriptors[len(descriptors)-1] 130 if descriptor.StopPosition == 0 { 131 return 0, fmt.Errorf("recording length zero") 132 } 133 134 // Return the last recordingID 135 return descriptor.RecordingId, nil 136 }