diff --git a/TODO.org b/TODO.org index 2d9882a..b007ee5 100644 --- a/TODO.org +++ b/TODO.org @@ -9,9 +9,9 @@ IPÊ - [ ] Escrever testes automatizados - [ ] SSL - [ ] Expvar - Canais, inscritos - - [ ] Otimizações [0/3] + - [-] Otimizações [1/3] - [ ] Refatorar partes do código, remover repetições - - [ ] Alterar tipos de dados de slices para mapas em alguns locais. + - [X] Alterar tipos de dados de slices para mapas em alguns locais. - [ ] Remover Canais vazios com uma go routine - Uma especie de coletor de lixo - [ ] Segurança, tempo de expiração, etc - [X] Dados extra na conexão do usuário. Ver Websockets onOpen diff --git a/app.go b/app.go index 6f2b4d9..bf9f008 100644 --- a/app.go +++ b/app.go @@ -25,24 +25,56 @@ type App struct { WebHooks bool URLWebHook string - PublicChannels []*Channel `json:"-"` - PresenceChannels []*Channel `json:"-"` - PrivateChannels []*Channel `json:"-"` - + Channels map[string]*Channel `json:"-"` Subscribers map[string]*Subscriber `json:"-"` } -// Returns a list of all channels in this app -func (a *App) AllChannels() []*Channel { +// Alloc memory for Subscribers and Channels +func (a *App) Init() { + a.Subscribers = make(map[string]*Subscriber) + a.Channels = make(map[string]*Channel) +} + +// Only Presence channels +func (a *App) PresenceChannels() []*Channel { var channels []*Channel - channels = append(channels, a.PrivateChannels...) - channels = append(channels, a.PresenceChannels...) - channels = append(channels, a.PublicChannels...) + for _, c := range a.Channels { + if c.IsPresence() { + channels = append(channels, c) + } + } return channels } +// Only Private channels +func (a *App) PrivateChannels() []*Channel { + var channels []*Channel + + for _, c := range a.Channels { + if c.IsPrivate() { + channels = append(channels, c) + } + } + + return channels +} + +// Only Public channels +func (a *App) PublicChannels() []*Channel { + var channels []*Channel + + for _, c := range a.Channels { + if c.IsPublic() { + channels = append(channels, c) + } + } + + return channels +} + +// Disconnect Socket func (a *App) Disconnect(socketID string) { log.Infof("Disconnecting socket %+v", socketID) @@ -54,7 +86,7 @@ func (a *App) Disconnect(socketID string) { } // Unsubscribe from channels - for _, c := range a.AllChannels() { + for _, c := range a.Channels { if c.IsSubscribed(s) { c.Unsubscribe(a, s) } @@ -72,7 +104,7 @@ func (a *App) Disconnect(socketID string) { a.Unlock() } -// Create a new Subscriber +// Connect a new Subscriber func (a *App) Connect(s *Subscriber) { log.Infof("Adding a new Subscriber %s to app %s", s.SocketID, a.Name) a.Lock() @@ -97,15 +129,7 @@ func (a *App) AddChannel(c *Channel) { log.Infof("Adding a new channel %s to app %s", c.ChannelID, a.Name) a.Lock() - - if c.IsPresence() { - a.PresenceChannels = append(a.PresenceChannels, c) - } else if c.IsPrivate() { - a.PrivateChannels = append(a.PrivateChannels, c) - } else { - a.PublicChannels = append(a.PublicChannels, c) - } - + a.Channels[c.ChannelID] = c a.Unlock() } @@ -125,10 +149,10 @@ func (a *App) FindOrCreateChannelByChannelID(n string) *Channel { // Find the channel by channel ID func (a *App) FindChannelByChannelID(n string) (*Channel, error) { - for _, c := range a.AllChannels() { - if c.ChannelID == n { - return c, nil - } + c, exists := a.Channels[n] + + if exists { + return c, nil } return nil, errors.New("Channel does not exists") diff --git a/config.go b/config.go index cb26f41..6388c6d 100644 --- a/config.go +++ b/config.go @@ -15,9 +15,10 @@ type ConfigFile struct { // Error for App not found var AppNotFoundError = errors.New("App not found") -func (c *ConfigFile) Initialize() { +// Initialize Apps +func (c *ConfigFile) Init() { for _, app := range c.Apps { - app.Subscribers = make(map[string]*Subscriber) + app.Init() } } diff --git a/conn.go b/conn.go index 8001db6..50e017b 100644 --- a/conn.go +++ b/conn.go @@ -9,7 +9,6 @@ import ( "errors" "strings" "sync" - "time" log "github.com/golang/glog" @@ -47,7 +46,7 @@ type Channel struct { CreatedAt time.Time ChannelID string - Subscriptions []*Subscription + Subscriptions map[string]*Subscription } // Return true if the channel has at least one subscriber @@ -60,6 +59,11 @@ func (c *Channel) IsPresenceOrPrivate() bool { return c.IsPresence() || c.IsPrivate() } +// Check if the type of the channel is public +func (c *Channel) IsPublic() bool { + return !c.IsPresence() && !c.IsPrivate() +} + // Check if the type of the channel is presence func (c *Channel) IsPresence() bool { return strings.HasPrefix(c.ChannelID, "presence-") @@ -86,7 +90,7 @@ func (c *Channel) Subscribe(a *App, s *Subscriber, data string) { log.Infof("Subscribing %s to channel %s", s.SocketID, c.ChannelID) c.Lock() - c.Subscriptions = append(c.Subscriptions, NewSubscription(s, data)) + c.Subscriptions[s.SocketID] = NewSubscription(s, data) c.Unlock() if c.IsPresence() { @@ -116,12 +120,8 @@ func (c *Channel) Subscribe(a *App, s *Subscriber, data string) { // IsSubscribed check if the user is subscribed func (c *Channel) IsSubscribed(s *Subscriber) bool { - for _, subs := range c.Subscriptions { - if subs.Subscriber == s { - return true - } - } - return false + _, exists := c.Subscriptions[s.SocketID] + return exists } // Remove the subscriber from the channel @@ -132,17 +132,13 @@ func (c *Channel) Unsubscribe(a *App, s *Subscriber) error { c.Lock() defer c.Unlock() - index := -1 - for i, subs := range c.Subscriptions { - if subs.Subscriber == s { - index = i - break - } - } - if index == -1 { + _, exists := c.Subscriptions[s.SocketID] + + if !exists { return errors.New("Subscription not found") } - c.Subscriptions = append(c.Subscriptions[:index], c.Subscriptions[index+1:]...) + + delete(c.Subscriptions, s.SocketID) if c.IsPresence() { // Publish pusher_internal:member_removed @@ -162,7 +158,7 @@ func (c *Channel) Unsubscribe(a *App, s *Subscriber) error { func NewChannel(channelID string) *Channel { log.Infof("Creating a new channel: %s", channelID) - return &Channel{ChannelID: channelID, CreatedAt: time.Now()} + return &Channel{ChannelID: channelID, CreatedAt: time.Now(), Subscriptions: make(map[string]*Subscription)} } // This function generate a sequencial ID diff --git a/main.go b/main.go index 57a58b6..de0169c 100644 --- a/main.go +++ b/main.go @@ -33,7 +33,7 @@ func main() { log.Fatal(err) } - Conf.Initialize() + Conf.Init() router := NewRouter() diff --git a/rest.go b/rest.go index 2238b55..a071a66 100644 --- a/rest.go +++ b/rest.go @@ -136,7 +136,7 @@ func GetChannels(w http.ResponseWriter, r *http.Request) { switch filter { case "presence-": - for _, c := range app.PresenceChannels { + for _, c := range app.PresenceChannels() { if requestedUserCount { channels[c.ChannelID] = struct { UserCount int `json:"user_count"` @@ -148,15 +148,15 @@ func GetChannels(w http.ResponseWriter, r *http.Request) { } } case "public-": - for _, c := range app.PublicChannels { + for _, c := range app.PublicChannels() { channels[c.ChannelID] = struct{}{} } case "private-": - for _, c := range app.PrivateChannels { + for _, c := range app.PrivateChannels() { channels[c.ChannelID] = struct{}{} } default: - for _, c := range app.AllChannels() { + for _, c := range app.Channels { channels[c.ChannelID] = struct{}{} } }