Browse Source
graph2: Added importLog query and associated models and repository functions.
module-madness-pointers
graph2: Added importLog query and associated models and repository functions.
module-madness-pointers
Gisle Aune
6 years ago
11 changed files with 282 additions and 6 deletions
-
2graph2/gqlgen.yml
-
45graph2/queries/log.go
-
3graph2/schema/root.gql
-
32graph2/schema/types/Log.gql
-
18internal/counter/counter.go
-
4internal/importers/forumlog/logs.go
-
8internal/importers/forumlog/logs_test.go
-
49models/log-importer.go
-
93models/logs/import.go
-
34models/posts/add-many.go
-
BINtest.prof
@ -0,0 +1,49 @@ |
|||||
|
package models |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"io" |
||||
|
"strconv" |
||||
|
) |
||||
|
|
||||
|
// LogImporter describes a model related log importing.
|
||||
|
type LogImporter string |
||||
|
|
||||
|
const ( |
||||
|
// LogImporterMircLike is a value of LogImporter
|
||||
|
LogImporterMircLike LogImporter = "MircLike" |
||||
|
// LogImporterForumLog is a value of LogImporter
|
||||
|
LogImporterForumLog LogImporter = "ForumLog" |
||||
|
) |
||||
|
|
||||
|
// IsValid returns true if the underlying string is one of the correct values.
|
||||
|
func (e LogImporter) IsValid() bool { |
||||
|
switch e { |
||||
|
case LogImporterForumLog, LogImporterMircLike: |
||||
|
return true |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
func (e LogImporter) String() string { |
||||
|
return string(e) |
||||
|
} |
||||
|
|
||||
|
// UnmarshalGQL unmarshals the underlying graphql value.
|
||||
|
func (e *LogImporter) UnmarshalGQL(v interface{}) error { |
||||
|
str, ok := v.(string) |
||||
|
if !ok { |
||||
|
return fmt.Errorf("enums must be strings") |
||||
|
} |
||||
|
|
||||
|
*e = LogImporter(str) |
||||
|
if !e.IsValid() { |
||||
|
return fmt.Errorf("%s is not a valid LogImporter", str) |
||||
|
} |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// MarshalGQL marshals the underlying graphql value.
|
||||
|
func (e LogImporter) MarshalGQL(w io.Writer) { |
||||
|
fmt.Fprint(w, strconv.Quote(e.String())) |
||||
|
} |
@ -0,0 +1,93 @@ |
|||||
|
package logs |
||||
|
|
||||
|
import ( |
||||
|
"errors" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/internal/importers/mirclike" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/models/posts" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/models/channels" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/internal/importers/forumlog" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/models" |
||||
|
) |
||||
|
|
||||
|
// An ImportedLog contains data about an imported log.
|
||||
|
type ImportedLog struct { |
||||
|
Log models.Log |
||||
|
Posts []models.Post |
||||
|
} |
||||
|
|
||||
|
// Import makes a log and posts object from different formats.
|
||||
|
func Import(importer models.LogImporter, date time.Time, tz *time.Location, channelName string, data string) ([]ImportedLog, error) { |
||||
|
results := make([]ImportedLog, 0, 8) |
||||
|
|
||||
|
eventName := "" |
||||
|
if channel, err := channels.FindName(channelName); err != nil { |
||||
|
eventName = channel.EventName |
||||
|
} |
||||
|
|
||||
|
date = date.In(tz) |
||||
|
|
||||
|
switch importer { |
||||
|
case models.LogImporterMircLike: |
||||
|
{ |
||||
|
if date.IsZero() { |
||||
|
return nil, errors.New("Date is not optional for mirc-like logs") |
||||
|
} |
||||
|
|
||||
|
parsedLog, parsedPosts, err := mirclike.ParseLog(data, date, true) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
log, err := Add(parsedLog.Date, channelName, "", eventName, "", false) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
posts, err := posts.AddMany(log, parsedPosts) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
results = append(results, ImportedLog{ |
||||
|
Log: log, |
||||
|
Posts: posts, |
||||
|
}) |
||||
|
} |
||||
|
case models.LogImporterForumLog: |
||||
|
{ |
||||
|
parseResults, err := forumlog.ParseLogs(data, tz) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
for _, result := range parseResults { |
||||
|
log, err := Add(result.Log.Date, channelName, "", eventName, "", false) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
posts, err := posts.AddMany(log, result.Posts) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
results = append(results, ImportedLog{ |
||||
|
Log: log, |
||||
|
Posts: posts, |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
default: |
||||
|
{ |
||||
|
return nil, errors.New("Invalid importer: " + importer.String()) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return results, nil |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
package posts |
||||
|
|
||||
|
import ( |
||||
|
"git.aiterp.net/rpdata/api/internal/counter" |
||||
|
"git.aiterp.net/rpdata/api/models" |
||||
|
) |
||||
|
|
||||
|
// AddMany adds multiple posts in on query. Each post gets a new ID and is associated with the log.
|
||||
|
func AddMany(log models.Log, posts []models.Post) ([]models.Post, error) { |
||||
|
docs := make([]interface{}, len(posts)) |
||||
|
|
||||
|
mutex.RLock() |
||||
|
defer mutex.RUnlock() |
||||
|
|
||||
|
startPosition, err := counter.NextMany("next_post_id", log.ShortID, len(posts)) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
for i, post := range posts { |
||||
|
post.ID = generateID(post.Time) |
||||
|
post.LogID = log.ShortID |
||||
|
post.Position = startPosition + i |
||||
|
|
||||
|
docs[i] = post |
||||
|
} |
||||
|
|
||||
|
err = collection.Insert(docs...) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return posts, nil |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue