11package consumer
22
33import (
4+ "ashishkujoy/queue/internal"
45 "ashishkujoy/queue/internal/config"
56 "encoding/binary"
67 "fmt"
@@ -30,12 +31,30 @@ func NewConsumerIndex(config *config.Config) (*ConsumerIndex, error) {
3031 return nil , err
3132 }
3233
33- return & ConsumerIndex {
34+ consumerIndex := & ConsumerIndex {
3435 writer : writer ,
3536 mu : & sync.RWMutex {},
3637 indexes : make (map [int ]int ),
3738 config : config ,
38- }, nil
39+ }
40+ return consumerIndex , nil
41+ }
42+
43+ func (ci * ConsumerIndex ) schedulePersist () {
44+ ticker := time .NewTicker (ci .config .ConsumerIndexSyncInterval ())
45+ go func () {
46+ for {
47+ select {
48+ case <- ticker .C :
49+ ci .mu .Lock ()
50+ err := ci .Persist ()
51+ ci .mu .Unlock ()
52+ if err != nil {
53+ fmt .Printf ("Error persisting consumer index: %v\n " , err )
54+ }
55+ }
56+ }
57+ }()
3958}
4059
4160func extractTimestamp (filename string ) int64 {
@@ -46,12 +65,20 @@ func extractTimestamp(filename string) int64 {
4665}
4766
4867func getLastIndexFile (config * config.Config ) (* os.File , error ) {
49- enteries , err := os .ReadDir (config .MetadataPath )
68+ files , err := getSortedIndexFiles (config )
69+ if err != nil {
70+ return nil , err
71+ }
72+ return files [0 ], nil
73+ }
74+
75+ func getSortedIndexFiles (config * config.Config ) ([]* os.File , error ) {
76+ entries , err := os .ReadDir (config .MetadataPath )
5077 if err != nil {
5178 return nil , err
5279 }
5380 var metadataTimestamp []int64
54- for _ , entry := range enteries {
81+ for _ , entry := range entries {
5582 if strings .Contains (entry .Name (), "consumer_index_" ) {
5683 metadataTimestamp = append (metadataTimestamp , extractTimestamp (entry .Name ()))
5784 }
@@ -62,10 +89,14 @@ func getLastIndexFile(config *config.Config) (*os.File, error) {
6289 sort .Slice (metadataTimestamp , func (i , j int ) bool {
6390 return metadataTimestamp [i ] > metadataTimestamp [j ]
6491 })
65- lastTimestamp := metadataTimestamp [0 ]
66- lastIndexFile := fmt .Sprintf ("%s/consumer_index_%d" , config .MetadataPath , lastTimestamp )
67-
68- return os .OpenFile (lastIndexFile , os .O_RDWR , 0666 )
92+ files := internal .Map (metadataTimestamp , func (i int64 ) * os.File {
93+ file , err := os .OpenFile (fmt .Sprintf ("%s/consumer_index_%d" , config .MetadataPath , i ), os .O_RDWR , 0666 )
94+ if err != nil {
95+ return nil
96+ }
97+ return file
98+ })
99+ return files , nil
69100}
70101
71102func restoreIndexesFromFile (file * os.File ) (map [int ]int , error ) {
@@ -78,11 +109,17 @@ func restoreIndexesFromFile(file *os.File) (map[int]int, error) {
78109 indexes := make (map [int ]int , stat .Size ()/ 8 )
79110 for i := int64 (0 ); i < indexSize ; i ++ {
80111 buf := make ([]byte , 4 )
81- file .ReadAt (buf , int64 (offset ))
112+ _ , err := file .ReadAt (buf , int64 (offset ))
113+ if err != nil {
114+ return nil , err
115+ }
82116 offset += 4
83117 consumerId := binary .BigEndian .Uint32 (buf )
84118 buf = make ([]byte , 4 )
85- file .ReadAt (buf , int64 (offset ))
119+ _ , err = file .ReadAt (buf , int64 (offset ))
120+ if err != nil {
121+ return nil , err
122+ }
86123 offset += 4
87124 consumerIndex := binary .BigEndian .Uint32 (buf )
88125 indexes [int (consumerId )] = int (consumerIndex )
@@ -192,12 +229,27 @@ func (ci *ConsumerIndex) CreateSnapshot() []byte {
192229}
193230
194231func (ci * ConsumerIndex ) Close () error {
232+ return ci .Persist ()
233+ }
234+
235+ func (ci * ConsumerIndex ) Persist () error {
195236 snapshot := ci .CreateSnapshot ()
196237 indexFile , err := createIndexFile (ci .config )
197238 if err != nil {
198239 return err
199240 }
200241 _ , err = indexFile .Write (snapshot )
201- indexFile .Sync ()
242+ err = indexFile .Sync ()
243+ if err != nil {
244+ return err
245+ }
246+ ci .writer = indexFile
247+ files , err := getSortedIndexFiles (ci .config )
248+ for _ , file := range files [1 :] {
249+ _ = file .Close ()
250+ }
251+ if err != nil {
252+ return err
253+ }
202254 return err
203255}
0 commit comments