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
Changed files
+23 -36
+1
go.mod
···
require (
github.com/bluesky-social/indigo v0.0.0-20250606055443-008e4ed915ad
github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e
+
github.com/cornelk/hashmap v1.0.8
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.3
)
+2
go.sum
···
github.com/caseyho/jetstream v0.0.0-20250310034359-bee7b7fc4d0f/go.mod h1:WiYEeyJSdUwqoaZ71KJSpTblemUCpwJfh5oVXplK6T4=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+
github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc=
+
github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+20 -36
main.go
···
"log"
"log/slog"
"net/http"
-
"sync"
"github.com/bluesky-social/indigo/api/bsky"
"github.com/bluesky-social/indigo/xrpc"
"github.com/bluesky-social/jetstream/pkg/client"
"github.com/bluesky-social/jetstream/pkg/models"
+
"github.com/cornelk/hashmap"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
···
// Global state
var (
-
subscribers = make(map[string]*SubscriberData)
-
subscribersMux sync.RWMutex
+
subscribers = hashmap.New[string, *SubscriberData]()
likeStream *client.Client
subscriberStream *client.Client
···
)
func getFollowsDids() []string {
-
subscribersMux.RLock()
-
defer subscribersMux.RUnlock()
-
var dids []string
-
for _, subscriber := range subscribers {
-
for follow, _ := range subscriber.ListenTo {
+
subscribers.Range(func(s string, sd *SubscriberData) bool {
+
for follow, _ := range sd.ListenTo {
dids = append(dids, follow)
}
-
}
-
+
return true
+
})
return dids
}
func getSubscriberDids() []string {
-
subscribersMux.RLock()
-
defer subscribersMux.RUnlock()
-
-
var dids []string
-
for did := range subscribers {
-
dids = append(dids, did)
-
}
-
+
dids := make([]string, 0, subscribers.Len())
+
subscribers.Range(func(s string, sd *SubscriberData) bool {
+
dids = append(dids, s)
+
return true
+
})
return dids
}
···
Reposts: reposts,
}
-
subscribersMux.Lock()
-
subscribers[did] = subscriber
-
subscribersMux.Unlock()
+
subscribers.Set(did, subscriber)
updateSubscriberStreamOpts()
updateLikeStreamOpts()
// delete subscriber after we are done
defer func() {
-
subscribersMux.Lock()
-
delete(subscribers, did)
-
subscribersMux.Unlock()
+
subscribers.Del(did)
updateSubscriberStreamOpts()
updateLikeStreamOpts()
}()
···
return nil
}
-
subscribersMux.RLock()
-
defer subscribersMux.RUnlock()
-
-
for _, subscriber := range subscribers {
-
for repostURI, _ := range subscriber.Reposts {
+
subscribers.Range(func(s string, sd *SubscriberData) bool {
+
for repostURI, _ := range sd.Reposts {
// (un)liked a post the subscriber reposted
if like.Subject.Uri == repostURI {
notification := NotificationMessage{
···
RepostURI: repostURI,
}
-
if err := subscriber.Conn.WriteJSON(notification); err != nil {
-
logger.Error("Failed to send notification", "subscriber", subscriber.DID, "error", err)
+
if err := sd.Conn.WriteJSON(notification); err != nil {
+
logger.Error("Failed to send notification", "subscriber", sd.DID, "error", err)
}
}
}
-
}
+
return true
+
})
return nil
}
···
return nil
}
-
subscribersMux.Lock()
-
defer subscribersMux.Unlock()
-
-
if subscriber, exists := subscribers[event.Did]; exists {
+
if subscriber, exists := subscribers.Get(event.Did); exists {
if event.Commit.Operation == models.CommitOperationDelete {
onDelete(subscriber, data)
} else {