Moved unknown nicks to log service
the build was successful

This commit is contained in:
2019-08-26 20:23:36 +02:00
parent 3b10c4d9b1
commit 0e70e37038
7 changed files with 62 additions and 95 deletions
+6 -14
View File
@@ -5,28 +5,20 @@ import (
"git.aiterp.net/rpdata/api/graph2/graphcore" "git.aiterp.net/rpdata/api/graph2/graphcore"
"git.aiterp.net/rpdata/api/models" "git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/unknownnicks"
) )
/// Queries /// Queries
func (r *queryResolver) UnknownNicks(ctx context.Context, filter *graphcore.UnknownNicksFilter) ([]*models.UnknownNick, error) { func (r *queryResolver) UnknownNicks(ctx context.Context, filter *graphcore.UnknownNicksFilter) ([]*models.UnknownNick, error) {
limit := 100 limit := 20
if filter != nil { if filter != nil {
if filter.Limit > 0 { limit = filter.Limit
limit = filter.Limit
}
} }
nicks, err := unknownnicks.List(limit) nicks := r.s.Logs.ListUnknownNicks()
if err != nil { if limit > 0 && len(nicks) > limit {
return nil, err nicks = nicks[:limit]
} }
nicks2 := make([]*models.UnknownNick, len(nicks)) return nicks, nil
for i := range nicks {
nicks2[i] = &nicks[i]
}
return nicks2, nil
} }
-37
View File
@@ -1,37 +0,0 @@
package unknownnicks
import (
"log"
"git.aiterp.net/rpdata/api/internal/store"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo"
)
var collection *mgo.Collection
func list(query interface{}, limit int) ([]models.UnknownNick, error) {
size := 64
if limit > 0 {
size = limit
}
posts := make([]models.UnknownNick, 0, size)
err := collection.Find(query).Limit(limit).Sort("-score").All(&posts)
if err != nil {
return nil, err
}
return posts, nil
}
func init() {
store.HandleInit(func(db *mgo.Database) {
collection = db.C("logbot3.unkownnicks")
err := collection.EnsureIndexKey("weight")
if err != nil {
log.Fatalln("init logbot3.unkownnicks:", err)
}
})
}
-10
View File
@@ -1,10 +0,0 @@
package unknownnicks
import (
"git.aiterp.net/rpdata/api/models"
)
// List lists the top N unknown nicks.
func List(limit int) ([]models.UnknownNick, error) {
return list(nil, limit)
}
-1
View File
@@ -1 +0,0 @@
package unknownnicks
-22
View File
@@ -1,22 +0,0 @@
package unknownnicks
import (
"github.com/globalsign/mgo/bson"
)
// Update updates the map, replacing it with the scores provided here.
func Update(updateMap map[string]int) error {
_, err := collection.RemoveAll(bson.M{})
if err != nil {
return err
}
for nick, score := range updateMap {
_, err := collection.UpsertId(nick, bson.M{"$set": bson.M{"score": score}})
if err != nil {
return err
}
}
return nil
}
+54 -11
View File
@@ -11,7 +11,9 @@ import (
"git.aiterp.net/rpdata/api/services/parsers" "git.aiterp.net/rpdata/api/services/parsers"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"log" "log"
"sort"
"strings" "strings"
"sync"
"time" "time"
) )
@@ -21,6 +23,9 @@ type LogService struct {
changeService *ChangeService changeService *ChangeService
channelService *ChannelService channelService *ChannelService
characterService *CharacterService characterService *CharacterService
unknownNicks map[string]int
unknownNicksMutex sync.Mutex
} }
func (s *LogService) Find(ctx context.Context, id string) (*models.Log, error) { func (s *LogService) Find(ctx context.Context, id string) (*models.Log, error) {
@@ -56,6 +61,24 @@ func (s *LogService) ListPosts(ctx context.Context, filter *models.PostFilter) (
return s.posts.List(ctx, *filter) return s.posts.List(ctx, *filter)
} }
func (s *LogService) ListUnknownNicks() []*models.UnknownNick {
s.unknownNicksMutex.Lock()
nicks := make([]*models.UnknownNick, 0, len(s.unknownNicks))
for nick, score := range s.unknownNicks {
nicks = append(nicks, &models.UnknownNick{
Nick: nick,
Score: score,
})
}
s.unknownNicksMutex.Unlock()
sort.Slice(nicks, func(i, j int) bool {
return nicks[i].Score > nicks[j].Score
})
return nicks
}
func (s *LogService) Create(ctx context.Context, title, description, channelName, eventName string, open bool) (*models.Log, error) { func (s *LogService) Create(ctx context.Context, title, description, channelName, eventName string, open bool) (*models.Log, error) {
if channelName == "" { if channelName == "" {
return nil, errors.New("channel name cannot be empty") return nil, errors.New("channel name cannot be empty")
@@ -280,8 +303,8 @@ func (s *LogService) SplitLog(ctx context.Context, logId string, startPostId str
s.changeService.Submit(ctx, models.ChangeModelPost, "add", true, changekeys.Many(newLog, newPosts), newPosts) s.changeService.Submit(ctx, models.ChangeModelPost, "add", true, changekeys.Many(newLog, newPosts), newPosts)
// Refresh character lists. // Refresh character lists.
_, _ = s.refreshLogCharacters(ctx, *l, nil) _, _ = s.refreshLogCharacters(ctx, *l, nil, false)
newLog2, err := s.refreshLogCharacters(ctx, *newLog, nil) newLog2, err := s.refreshLogCharacters(ctx, *newLog, nil, false)
if err == nil { if err == nil {
newLog = newLog2 newLog = newLog2
} }
@@ -339,7 +362,7 @@ func (s *LogService) MergeLogs(ctx context.Context, targetID string, sourceID st
} }
// Refresh characters // Refresh characters
target2, err := s.refreshLogCharacters(ctx, *target, nil) target2, err := s.refreshLogCharacters(ctx, *target, nil, false)
if err != nil { if err != nil {
log.Printf("Failed to update characters in log %s: %s", target.ID, err) log.Printf("Failed to update characters in log %s: %s", target.ID, err)
} else { } else {
@@ -379,7 +402,7 @@ func (s *LogService) AddPost(ctx context.Context, logId string, time time.Time,
return nil, err return nil, err
} }
l2, err := s.refreshLogCharacters(ctx, *l, nil) l2, err := s.refreshLogCharacters(ctx, *l, nil, false)
if err != nil { if err != nil {
log.Printf("Failed to update characters in log %s: %s", l.ID, err) log.Printf("Failed to update characters in log %s: %s", l.ID, err)
} else { } else {
@@ -416,7 +439,7 @@ func (s *LogService) EditPost(ctx context.Context, id string, update models.Post
return return
} }
_, err = s.refreshLogCharacters(ctx, *l, nil) _, err = s.refreshLogCharacters(ctx, *l, nil, false)
if err != nil { if err != nil {
log.Printf("Failed to update characters in log %s: %s", l.ID, err) log.Printf("Failed to update characters in log %s: %s", l.ID, err)
} }
@@ -483,7 +506,7 @@ func (s *LogService) DeletePost(ctx context.Context, id string) (*models.Post, e
return return
} }
_, err = s.refreshLogCharacters(ctx, *l, nil) _, err = s.refreshLogCharacters(ctx, *l, nil, false)
if err != nil { if err != nil {
log.Printf("Failed to update characters in log %s: %s", l.ID, err) log.Printf("Failed to update characters in log %s: %s", l.ID, err)
} }
@@ -638,12 +661,18 @@ func (s *LogService) RefreshAllLogCharacters(ctx context.Context) error {
} }
characterMap := s.makeCharacterMap(characters) characterMap := s.makeCharacterMap(characters)
s.unknownNicksMutex.Lock()
for key := range s.unknownNicks {
delete(s.unknownNicks, key)
}
s.unknownNicksMutex.Unlock()
eg := errgroup.Group{} eg := errgroup.Group{}
for i := range logs { for i := range logs {
l := logs[i] l := logs[i]
eg.Go(func() error { eg.Go(func() error {
_, err := s.refreshLogCharacters(ctx, *l, characterMap) _, err := s.refreshLogCharacters(ctx, *l, characterMap, true)
return err return err
}) })
} }
@@ -652,16 +681,20 @@ func (s *LogService) RefreshAllLogCharacters(ctx context.Context) error {
return err return err
} }
log.Printf("Full log character refresh complete; nicks: %d, logs: %d, duration: %s", len(characterMap), len(logs), time.Since(start)) s.unknownNicksMutex.Lock()
unknownCount := len(s.unknownNicks)
s.unknownNicksMutex.Unlock()
log.Printf("Full log character refresh complete; nicks: %d, unknowns: %d, logs: %d, duration: %s", len(characterMap), unknownCount, len(logs), time.Since(start))
return nil return nil
} }
func (s *LogService) RefreshLogCharacters(ctx context.Context, log models.Log) (*models.Log, error) { func (s *LogService) RefreshLogCharacters(ctx context.Context, log models.Log) (*models.Log, error) {
return s.refreshLogCharacters(ctx, log, nil) return s.refreshLogCharacters(ctx, log, nil, false)
} }
func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, characterMap map[string]*models.Character) (*models.Log, error) { func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, characterMap map[string]*models.Character, useUnknownNicks bool) (*models.Log, error) {
posts, err := s.ListPosts(ctx, &models.PostFilter{LogID: &log.ShortID}) posts, err := s.ListPosts(ctx, &models.PostFilter{LogID: &log.ShortID})
if err != nil { if err != nil {
return &log, nil return &log, nil
@@ -718,9 +751,19 @@ func (s *LogService) refreshLogCharacters(ctx context.Context, log models.Log, c
for key := range added { for key := range added {
delete(added, key) delete(added, key)
} }
unknowned := make(map[string]bool)
for _, nick := range nicks { for _, nick := range nicks {
character := characterMap[nick] character := characterMap[nick]
if character == nil || added[character.ID] { if character == nil {
if useUnknownNicks && !unknowned[nick] {
unknowned[nick] = true
s.unknownNicksMutex.Lock()
s.unknownNicks[nick]++
s.unknownNicksMutex.Unlock()
}
continue
} else if added[character.ID] {
continue continue
} }
added[character.ID] = true added[character.ID] = true
+2
View File
@@ -38,6 +38,8 @@ func NewBundle(db database.Database) *Bundle {
changeService: bundle.Changes, changeService: bundle.Changes,
channelService: bundle.Channels, channelService: bundle.Channels,
characterService: bundle.Characters, characterService: bundle.Characters,
unknownNicks: make(map[string]int, 512),
} }
bundle.Stories = &StoryService{ bundle.Stories = &StoryService{
stories: db.Stories(), stories: db.Stories(),