its for when you want to get like notifications for your reposts

refactor: use cornelk hashmap instead of using a map with a mutex lol

ptr.pet b16df182 ad439ec8

verified
+23 -36
+1
go.mod
··· 5 5 require ( 6 6 github.com/bluesky-social/indigo v0.0.0-20250606055443-008e4ed915ad 7 7 github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e 8 + github.com/cornelk/hashmap v1.0.8 8 9 github.com/gorilla/mux v1.8.1 9 10 github.com/gorilla/websocket v1.5.3 10 11 )
+2
go.sum
··· 12 12 github.com/caseyho/jetstream v0.0.0-20250310034359-bee7b7fc4d0f/go.mod h1:WiYEeyJSdUwqoaZ71KJSpTblemUCpwJfh5oVXplK6T4= 13 13 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 14 14 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 15 + github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= 16 + github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= 15 17 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 16 18 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 17 19 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+20 -36
main.go
··· 6 6 "log" 7 7 "log/slog" 8 8 "net/http" 9 - "sync" 10 9 11 10 "github.com/bluesky-social/indigo/api/bsky" 12 11 "github.com/bluesky-social/indigo/xrpc" 13 12 "github.com/bluesky-social/jetstream/pkg/client" 14 13 "github.com/bluesky-social/jetstream/pkg/models" 14 + "github.com/cornelk/hashmap" 15 15 "github.com/gorilla/mux" 16 16 "github.com/gorilla/websocket" 17 17 ) ··· 34 34 35 35 // Global state 36 36 var ( 37 - subscribers = make(map[string]*SubscriberData) 38 - subscribersMux sync.RWMutex 37 + subscribers = hashmap.New[string, *SubscriberData]() 39 38 40 39 likeStream *client.Client 41 40 subscriberStream *client.Client ··· 50 49 ) 51 50 52 51 func getFollowsDids() []string { 53 - subscribersMux.RLock() 54 - defer subscribersMux.RUnlock() 55 - 56 52 var dids []string 57 - for _, subscriber := range subscribers { 58 - for follow, _ := range subscriber.ListenTo { 53 + subscribers.Range(func(s string, sd *SubscriberData) bool { 54 + for follow, _ := range sd.ListenTo { 59 55 dids = append(dids, follow) 60 56 } 61 - } 62 - 57 + return true 58 + }) 63 59 return dids 64 60 } 65 61 66 62 func getSubscriberDids() []string { 67 - subscribersMux.RLock() 68 - defer subscribersMux.RUnlock() 69 - 70 - var dids []string 71 - for did := range subscribers { 72 - dids = append(dids, did) 73 - } 74 - 63 + dids := make([]string, 0, subscribers.Len()) 64 + subscribers.Range(func(s string, sd *SubscriberData) bool { 65 + dids = append(dids, s) 66 + return true 67 + }) 75 68 return dids 76 69 } 77 70 ··· 137 130 Reposts: reposts, 138 131 } 139 132 140 - subscribersMux.Lock() 141 - subscribers[did] = subscriber 142 - subscribersMux.Unlock() 133 + subscribers.Set(did, subscriber) 143 134 updateSubscriberStreamOpts() 144 135 updateLikeStreamOpts() 145 136 // delete subscriber after we are done 146 137 defer func() { 147 - subscribersMux.Lock() 148 - delete(subscribers, did) 149 - subscribersMux.Unlock() 138 + subscribers.Del(did) 150 139 updateSubscriberStreamOpts() 151 140 updateLikeStreamOpts() 152 141 }() ··· 215 204 return nil 216 205 } 217 206 218 - subscribersMux.RLock() 219 - defer subscribersMux.RUnlock() 220 - 221 - for _, subscriber := range subscribers { 222 - for repostURI, _ := range subscriber.Reposts { 207 + subscribers.Range(func(s string, sd *SubscriberData) bool { 208 + for repostURI, _ := range sd.Reposts { 223 209 // (un)liked a post the subscriber reposted 224 210 if like.Subject.Uri == repostURI { 225 211 notification := NotificationMessage{ ··· 228 214 RepostURI: repostURI, 229 215 } 230 216 231 - if err := subscriber.Conn.WriteJSON(notification); err != nil { 232 - logger.Error("Failed to send notification", "subscriber", subscriber.DID, "error", err) 217 + if err := sd.Conn.WriteJSON(notification); err != nil { 218 + logger.Error("Failed to send notification", "subscriber", sd.DID, "error", err) 233 219 } 234 220 } 235 221 } 236 - } 222 + return true 223 + }) 237 224 238 225 return nil 239 226 } ··· 278 265 return nil 279 266 } 280 267 281 - subscribersMux.Lock() 282 - defer subscribersMux.Unlock() 283 - 284 - if subscriber, exists := subscribers[event.Did]; exists { 268 + if subscriber, exists := subscribers.Get(event.Did); exists { 285 269 if event.Commit.Operation == models.CommitOperationDelete { 286 270 onDelete(subscriber, data) 287 271 } else {