make new engine primary, rename package

This commit is contained in:
Umputun
2019-06-25 20:06:30 -05:00
parent 92d9b7703d
commit 3aba348e87
23 changed files with 702 additions and 703 deletions
+5 -5
View File
@@ -31,7 +31,7 @@ import (
"github.com/umputun/remark/backend/app/rest/proxy"
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/image"
"github.com/umputun/remark/backend/app/store/service"
)
@@ -401,7 +401,7 @@ func (a *serverApp) activateBackup(ctx context.Context) {
}
// makeDataStore creates store for all sites
func (s *ServerCommand) makeDataStore() (result engine2.Interface, err error) {
func (s *ServerCommand) makeDataStore() (result engine.Interface, err error) {
log.Printf("[INFO] make data store, type=%s", s.Store.Type)
switch s.Store.Type {
@@ -409,11 +409,11 @@ func (s *ServerCommand) makeDataStore() (result engine2.Interface, err error) {
if err = makeDirs(s.Store.Bolt.Path); err != nil {
return nil, errors.Wrap(err, "failed to create bolt store")
}
sites := []engine2.BoltSite{}
sites := []engine.BoltSite{}
for _, site := range s.Sites {
sites = append(sites, engine2.BoltSite{SiteID: site, FileName: fmt.Sprintf("%s/%s.db", s.Store.Bolt.Path, site)})
sites = append(sites, engine.BoltSite{SiteID: site, FileName: fmt.Sprintf("%s/%s.db", s.Store.Bolt.Path, site)})
}
result, err = engine2.NewBoltDB(bolt.Options{Timeout: s.Store.Bolt.Timeout}, sites...)
result, err = engine.NewBoltDB(bolt.Options{Timeout: s.Store.Bolt.Timeout}, sites...)
// case "mongo":
// mgServer, e := s.makeMongo()
// if e != nil {
+2 -2
View File
@@ -12,13 +12,13 @@ import (
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/service"
)
func TestDisqus_Import(t *testing.T) {
defer os.Remove("/tmp/remark-test.db")
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
require.Nil(t, err, "create store")
dataStore := service.DataStore{Engine: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}
d := Disqus{DataStore: &dataStore}
+5 -5
View File
@@ -12,7 +12,7 @@ import (
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/service"
)
@@ -25,7 +25,7 @@ func TestMigrator_ImportDisqus(t *testing.T) {
err := ioutil.WriteFile("/tmp/disqus-test.xml", []byte(xmlTestDisqus), 0600)
require.Nil(t, err)
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
require.Nil(t, err, "create store")
dataStore := &service.DataStore{Engine: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}
size, err := ImportComments(ImportParams{
@@ -51,7 +51,7 @@ func TestMigrator_ImportWordPress(t *testing.T) {
err := ioutil.WriteFile("/tmp/wordpress-test.xml", []byte(xmlTestWP), 0600)
require.Nil(t, err)
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
require.Nil(t, err, "create store")
dataStore := &service.DataStore{Engine: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}
size, err := ImportComments(ImportParams{
@@ -80,7 +80,7 @@ func TestMigrator_ImportNative(t *testing.T) {
err := ioutil.WriteFile("/tmp/disqus-test.r42", []byte(data), 0600)
require.Nil(t, err)
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "radio-t"})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "radio-t"})
require.Nil(t, err, "create store")
dataStore := &service.DataStore{Engine: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}
@@ -100,7 +100,7 @@ func TestMigrator_ImportNative(t *testing.T) {
func TestMigrator_ImportFailed(t *testing.T) {
defer os.Remove("/tmp/remark-test.db")
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: "test"})
require.Nil(t, err, "create store")
dataStore := &service.DataStore{Engine: b}
_, err = ImportComments(ImportParams{
+2 -2
View File
@@ -16,7 +16,7 @@ import (
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/service"
)
@@ -142,7 +142,7 @@ func TestNative_ImportManyWithError(t *testing.T) {
func prep(t *testing.T) *service.DataStore {
os.Remove(testDb)
boltStore, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{SiteID: "radio-t", FileName: testDb})
boltStore, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{SiteID: "radio-t", FileName: testDb})
assert.Nil(t, err)
b := &service.DataStore{Engine: boltStore, AdminStore: admin.NewStaticStore("12345", []string{}, "")}
+2 -2
View File
@@ -11,14 +11,14 @@ import (
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/service"
)
func TestWordPress_Import(t *testing.T) {
siteID := "testWP"
defer func() { _ = os.Remove("/tmp/remark-test.db") }()
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/remark-test.db", SiteID: siteID})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/remark-test.db", SiteID: siteID})
assert.Nil(t, err, "create store")
dataStore := service.DataStore{Engine: b, AdminStore: admin.NewStaticStore("12345", []string{}, "")}
+2 -2
View File
@@ -31,7 +31,7 @@ import (
"github.com/umputun/remark/backend/app/rest/proxy"
"github.com/umputun/remark/backend/app/store"
adminstore "github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/image"
"github.com/umputun/remark/backend/app/store/service"
)
@@ -291,7 +291,7 @@ func startupT(t *testing.T) (ts *httptest.Server, srv *Rest, teardown func()) {
os.RemoveAll("/tmp/ava-remark42")
os.RemoveAll("/tmp/pics-remark42")
b, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: testDb, SiteID: "radio-t"})
b, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: testDb, SiteID: "radio-t"})
require.Nil(t, err)
memCache, err := cache.NewMemoryCache()
@@ -1,4 +1,4 @@
package engine2
package engine
import (
"bytes"
@@ -1,4 +1,4 @@
package engine2
package engine
import (
"fmt"
+64 -23
View File
@@ -1,6 +1,7 @@
package engine
// Package engine defines interfaces each supported storage should implement.
// Includes default implementation with boltdb
package engine
import (
"sort"
@@ -15,28 +16,68 @@ import (
// Interface defines methods provided by low-level storage engine
type Interface interface {
Create(comment store.Comment) (commentID string, err error) // create new comment, avoid dups by id
Get(locator store.Locator, commentID string) (store.Comment, error) // get comment by id
Put(locator store.Locator, comment store.Comment) error // update comment, mutable parts only
Find(locator store.Locator, sort string) ([]store.Comment, error) // find comments for locator
Last(siteID string, limit int, since time.Time) ([]store.Comment, error) // last comments for given site, sorted by time
User(siteID, userID string, limit, skip int) ([]store.Comment, error) // comments by user, sorted by time
UserCount(siteID, userID string) (int, error) // comments count by user
Count(locator store.Locator) (int, error) // number of comments for the post
List(siteID string, limit int, skip int) ([]store.PostInfo, error) // list of commented posts
Info(locator store.Locator, readonlyAge int) (store.PostInfo, error) // get post info
Delete(locator store.Locator, commentID string, mode store.DeleteMode) error // delete comment by id
DeleteAll(siteID string) error // delete all data from site
DeleteUser(siteID string, userID string) error // remove all comments from user
SetBlock(siteID string, userID string, status bool, ttl time.Duration) error // block or unblock user with TTL (0-permanent)
IsBlocked(siteID string, userID string) bool // check if user blocked
Blocked(siteID string) ([]store.BlockedUser, error) // get list of blocked users
SetReadOnly(locator store.Locator, status bool) error // set/reset read-only flag
IsReadOnly(locator store.Locator) bool // check if post read-only
SetVerified(siteID string, userID string, status bool) error // set/reset verified flag
IsVerified(siteID string, userID string) bool // check verified status
Verified(siteID string) ([]string, error) // list of verified user ids
Close() error // close/stop engine
Create(comment store.Comment) (commentID string, err error) // create new comment, avoid dups by id
Update(locator store.Locator, comment store.Comment) error // update comment, mutable parts only
Get(locator store.Locator, commentID string) (store.Comment, error) // get comment by id
Find(req FindRequest) ([]store.Comment, error) // find comments for locator or site
Info(req InfoRequest) ([]store.PostInfo, error) // get post(s) meta info
Count(req FindRequest) (int, error) // get count for post or user
Delete(req DeleteRequest) error // delete post(s) by id or by userID
Flag(req FlagRequest) (bool, error) // set and get flags
ListFlags(siteID string, flag Flag) ([]interface{}, error) // get list of flagged keys, like blocked & verified user
Close() error // close storage engine
}
// FindRequest is the input for all find operations
type FindRequest struct {
Locator store.Locator // lack of URL means site operation
UserID string // presence of UserID treated as user-related find
Sort string // sort order with +/-field syntax
Since time.Time // time limit for found results
Limit, Skip int
}
// InfoRequest is the input of Info operation used to get meta data about posts
type InfoRequest struct {
Locator store.Locator
Limit, Skip int
ReadOnlyAge int
}
type DeleteRequest struct {
Locator store.Locator // lack of URL means site operation
CommentID string
UserID string
DeleteMode store.DeleteMode
}
// Flag defines type of binary attribute
type Flag string
// FlagStatus represents values of the flag update
type FlagStatus int
// enum of update values
const (
FlagNonSet FlagStatus = 0
FlagTrue FlagStatus = 1
FlagFalse FlagStatus = -1
)
// Enum of all flags
const (
ReadOnly = Flag("readonly")
Verified = Flag("verified")
Blocked = Flag("blocked")
)
// FlagRequest is the input for both get/set for flags, like blocked, verified and so on
type FlagRequest struct {
Flag Flag // flag type
Locator store.Locator // post locator
UserID string // for flags setting user status
Update FlagStatus // if FlagNonSet it will be get op, if set will set the value
TTL time.Duration // ttl for time-sensitive flags only, like blocked for some period
}
const (
+72 -275
View File
@@ -3,36 +3,12 @@ package engine
import mock "github.com/stretchr/testify/mock"
import store "github.com/umputun/remark/backend/app/store"
import time "time"
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
// Blocked provides a mock function with given fields: siteID
func (_m *MockInterface) Blocked(siteID string) ([]store.BlockedUser, error) {
ret := _m.Called(siteID)
var r0 []store.BlockedUser
if rf, ok := ret.Get(0).(func(string) []store.BlockedUser); ok {
r0 = rf(siteID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.BlockedUser)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(siteID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Close provides a mock function with given fields:
func (_m *MockInterface) Close() error {
ret := _m.Called()
@@ -47,20 +23,20 @@ func (_m *MockInterface) Close() error {
return r0
}
// Count provides a mock function with given fields: locator
func (_m *MockInterface) Count(locator store.Locator) (int, error) {
ret := _m.Called(locator)
// Count provides a mock function with given fields: req
func (_m *MockInterface) Count(req FindRequest) (int, error) {
ret := _m.Called(req)
var r0 int
if rf, ok := ret.Get(0).(func(store.Locator) int); ok {
r0 = rf(locator)
if rf, ok := ret.Get(0).(func(FindRequest) int); ok {
r0 = rf(req)
} else {
r0 = ret.Get(0).(int)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator) error); ok {
r1 = rf(locator)
if rf, ok := ret.Get(1).(func(FindRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
@@ -89,13 +65,13 @@ func (_m *MockInterface) Create(comment store.Comment) (string, error) {
return r0, r1
}
// Delete provides a mock function with given fields: locator, commentID, mode
func (_m *MockInterface) Delete(locator store.Locator, commentID string, mode store.DeleteMode) error {
ret := _m.Called(locator, commentID, mode)
// Delete provides a mock function with given fields: req
func (_m *MockInterface) Delete(req DeleteRequest) error {
ret := _m.Called(req)
var r0 error
if rf, ok := ret.Get(0).(func(store.Locator, string, store.DeleteMode) error); ok {
r0 = rf(locator, commentID, mode)
if rf, ok := ret.Get(0).(func(DeleteRequest) error); ok {
r0 = rf(req)
} else {
r0 = ret.Error(0)
}
@@ -103,41 +79,13 @@ func (_m *MockInterface) Delete(locator store.Locator, commentID string, mode st
return r0
}
// DeleteAll provides a mock function with given fields: siteID
func (_m *MockInterface) DeleteAll(siteID string) error {
ret := _m.Called(siteID)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(siteID)
} else {
r0 = ret.Error(0)
}
return r0
}
// DeleteUser provides a mock function with given fields: siteID, userID
func (_m *MockInterface) DeleteUser(siteID string, userID string) error {
ret := _m.Called(siteID, userID)
var r0 error
if rf, ok := ret.Get(0).(func(string, string) error); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Error(0)
}
return r0
}
// Find provides a mock function with given fields: locator, sort
func (_m *MockInterface) Find(locator store.Locator, sort string) ([]store.Comment, error) {
ret := _m.Called(locator, sort)
// Find provides a mock function with given fields: req
func (_m *MockInterface) Find(req FindRequest) ([]store.Comment, error) {
ret := _m.Called(req)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(store.Locator, string) []store.Comment); ok {
r0 = rf(locator, sort)
if rf, ok := ret.Get(0).(func(FindRequest) []store.Comment); ok {
r0 = rf(req)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
@@ -145,8 +93,29 @@ func (_m *MockInterface) Find(locator store.Locator, sort string) ([]store.Comme
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator, string) error); ok {
r1 = rf(locator, sort)
if rf, ok := ret.Get(1).(func(FindRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Flag provides a mock function with given fields: req
func (_m *MockInterface) Flag(req FlagRequest) (bool, error) {
ret := _m.Called(req)
var r0 bool
if rf, ok := ret.Get(0).(func(FlagRequest) bool); ok {
r0 = rf(req)
} else {
r0 = ret.Get(0).(bool)
}
var r1 error
if rf, ok := ret.Get(1).(func(FlagRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
@@ -175,99 +144,13 @@ func (_m *MockInterface) Get(locator store.Locator, commentID string) (store.Com
return r0, r1
}
// Info provides a mock function with given fields: locator, readonlyAge
func (_m *MockInterface) Info(locator store.Locator, readonlyAge int) (store.PostInfo, error) {
ret := _m.Called(locator, readonlyAge)
var r0 store.PostInfo
if rf, ok := ret.Get(0).(func(store.Locator, int) store.PostInfo); ok {
r0 = rf(locator, readonlyAge)
} else {
r0 = ret.Get(0).(store.PostInfo)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator, int) error); ok {
r1 = rf(locator, readonlyAge)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// IsBlocked provides a mock function with given fields: siteID, userID
func (_m *MockInterface) IsBlocked(siteID string, userID string) bool {
ret := _m.Called(siteID, userID)
var r0 bool
if rf, ok := ret.Get(0).(func(string, string) bool); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// IsReadOnly provides a mock function with given fields: locator
func (_m *MockInterface) IsReadOnly(locator store.Locator) bool {
ret := _m.Called(locator)
var r0 bool
if rf, ok := ret.Get(0).(func(store.Locator) bool); ok {
r0 = rf(locator)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// IsVerified provides a mock function with given fields: siteID, userID
func (_m *MockInterface) IsVerified(siteID string, userID string) bool {
ret := _m.Called(siteID, userID)
var r0 bool
if rf, ok := ret.Get(0).(func(string, string) bool); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// Last provides a mock function with given fields: siteID, limit, since
func (_m *MockInterface) Last(siteID string, limit int, since time.Time) ([]store.Comment, error) {
ret := _m.Called(siteID, limit, since)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(string, int, time.Time) []store.Comment); ok {
r0 = rf(siteID, limit, since)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, int, time.Time) error); ok {
r1 = rf(siteID, limit, since)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// List provides a mock function with given fields: siteID, limit, skip
func (_m *MockInterface) List(siteID string, limit int, skip int) ([]store.PostInfo, error) {
ret := _m.Called(siteID, limit, skip)
// Info provides a mock function with given fields: req
func (_m *MockInterface) Info(req InfoRequest) ([]store.PostInfo, error) {
ret := _m.Called(req)
var r0 []store.PostInfo
if rf, ok := ret.Get(0).(func(string, int, int) []store.PostInfo); ok {
r0 = rf(siteID, limit, skip)
if rf, ok := ret.Get(0).(func(InfoRequest) []store.PostInfo); ok {
r0 = rf(req)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.PostInfo)
@@ -275,8 +158,8 @@ func (_m *MockInterface) List(siteID string, limit int, skip int) ([]store.PostI
}
var r1 error
if rf, ok := ret.Get(1).(func(string, int, int) error); ok {
r1 = rf(siteID, limit, skip)
if rf, ok := ret.Get(1).(func(InfoRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
@@ -284,8 +167,31 @@ func (_m *MockInterface) List(siteID string, limit int, skip int) ([]store.PostI
return r0, r1
}
// Put provides a mock function with given fields: locator, comment
func (_m *MockInterface) Put(locator store.Locator, comment store.Comment) error {
// ListFlags provides a mock function with given fields: siteID, flag
func (_m *MockInterface) ListFlags(siteID string, flag Flag) ([]interface{}, error) {
ret := _m.Called(siteID, flag)
var r0 []interface{}
if rf, ok := ret.Get(0).(func(string, Flag) []interface{}); ok {
r0 = rf(siteID, flag)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]interface{})
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, Flag) error); ok {
r1 = rf(siteID, flag)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Update provides a mock function with given fields: locator, comment
func (_m *MockInterface) Update(locator store.Locator, comment store.Comment) error {
ret := _m.Called(locator, comment)
var r0 error
@@ -297,112 +203,3 @@ func (_m *MockInterface) Put(locator store.Locator, comment store.Comment) error
return r0
}
// SetBlock provides a mock function with given fields: siteID, userID, status, ttl
func (_m *MockInterface) SetBlock(siteID string, userID string, status bool, ttl time.Duration) error {
ret := _m.Called(siteID, userID, status, ttl)
var r0 error
if rf, ok := ret.Get(0).(func(string, string, bool, time.Duration) error); ok {
r0 = rf(siteID, userID, status, ttl)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetReadOnly provides a mock function with given fields: locator, status
func (_m *MockInterface) SetReadOnly(locator store.Locator, status bool) error {
ret := _m.Called(locator, status)
var r0 error
if rf, ok := ret.Get(0).(func(store.Locator, bool) error); ok {
r0 = rf(locator, status)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetVerified provides a mock function with given fields: siteID, userID, status
func (_m *MockInterface) SetVerified(siteID string, userID string, status bool) error {
ret := _m.Called(siteID, userID, status)
var r0 error
if rf, ok := ret.Get(0).(func(string, string, bool) error); ok {
r0 = rf(siteID, userID, status)
} else {
r0 = ret.Error(0)
}
return r0
}
// User provides a mock function with given fields: siteID, userID, limit, skip
func (_m *MockInterface) User(siteID string, userID string, limit int, skip int) ([]store.Comment, error) {
ret := _m.Called(siteID, userID, limit, skip)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(string, string, int, int) []store.Comment); ok {
r0 = rf(siteID, userID, limit, skip)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, int, int) error); ok {
r1 = rf(siteID, userID, limit, skip)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// UserCount provides a mock function with given fields: siteID, userID
func (_m *MockInterface) UserCount(siteID string, userID string) (int, error) {
ret := _m.Called(siteID, userID)
var r0 int
if rf, ok := ret.Get(0).(func(string, string) int); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Get(0).(int)
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string) error); ok {
r1 = rf(siteID, userID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Verified provides a mock function with given fields: siteID
func (_m *MockInterface) Verified(siteID string) ([]string, error) {
ret := _m.Called(siteID)
var r0 []string
if rf, ok := ret.Get(0).(func(string) []string); ok {
r0 = rf(siteID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(siteID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
-128
View File
@@ -1,128 +0,0 @@
package engine2
// Package engine defines interfaces each supported storage should implement.
// Includes default implementation with boltdb
import (
"sort"
"strings"
"time"
"github.com/umputun/remark/backend/app/store"
)
// NOTE: mockery works from linked to go-path and with GOFLAGS='-mod=vendor' go generate
//go:generate sh -c "mockery -inpkg -name Interface -print > /tmp/engine-mock.tmp && mv /tmp/engine-mock.tmp engine_mock.go"
// Interface defines methods provided by low-level storage engine
type Interface interface {
Create(comment store.Comment) (commentID string, err error) // create new comment, avoid dups by id
Update(locator store.Locator, comment store.Comment) error // update comment, mutable parts only
Get(locator store.Locator, commentID string) (store.Comment, error) // get comment by id
Find(req FindRequest) ([]store.Comment, error) // find comments for locator or site
Info(req InfoRequest) ([]store.PostInfo, error) // get post(s) meta info
Count(req FindRequest) (int, error) // get count for post or user
Delete(req DeleteRequest) error // delete post(s) by id or by userID
Flag(req FlagRequest) (bool, error) // set and get flags
ListFlags(siteID string, flag Flag) ([]interface{}, error) // get list of flagged keys, like blocked & verified user
Close() error // close storage engine
}
// FindRequest is the input for all find operations
type FindRequest struct {
Locator store.Locator // lack of URL means site operation
UserID string // presence of UserID treated as user-related find
Sort string // sort order with +/-field syntax
Since time.Time // time limit for found results
Limit, Skip int
}
// InfoRequest is the input of Info operation used to get meta data about posts
type InfoRequest struct {
Locator store.Locator
Limit, Skip int
ReadOnlyAge int
}
type DeleteRequest struct {
Locator store.Locator // lack of URL means site operation
CommentID string
UserID string
DeleteMode store.DeleteMode
}
// Flag defines type of binary attribute
type Flag string
// FlagStatus represents values of the flag update
type FlagStatus int
// enum of update values
const (
FlagNonSet FlagStatus = 0
FlagTrue FlagStatus = 1
FlagFalse FlagStatus = -1
)
// Enum of all flags
const (
ReadOnly = Flag("readonly")
Verified = Flag("verified")
Blocked = Flag("blocked")
)
// FlagRequest is the input for both get/set for flags, like blocked, verified and so on
type FlagRequest struct {
Flag Flag // flag type
Locator store.Locator // post locator
UserID string // for flags setting user status
Update FlagStatus // if FlagNonSet it will be get op, if set will set the value
TTL time.Duration // ttl for time-sensitive flags only, like blocked for some period
}
const (
// limits
lastLimit = 1000
userLimit = 500
)
// SortComments is for engines can't sort data internally
func SortComments(comments []store.Comment, sortFld string) []store.Comment {
sort.Slice(comments, func(i, j int) bool {
switch sortFld {
case "+time", "-time", "time", "+active", "-active", "active":
if strings.HasPrefix(sortFld, "-") {
return comments[i].Timestamp.After(comments[j].Timestamp)
}
return comments[i].Timestamp.Before(comments[j].Timestamp)
case "+score", "-score", "score":
if strings.HasPrefix(sortFld, "-") {
if comments[i].Score == comments[j].Score {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Score > comments[j].Score
}
if comments[i].Score == comments[j].Score {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Score < comments[j].Score
case "+controversy", "-controversy", "controversy":
if strings.HasPrefix(sortFld, "-") {
if comments[i].Controversy == comments[j].Controversy {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Controversy > comments[j].Controversy
}
if comments[i].Controversy == comments[j].Controversy {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Controversy < comments[j].Controversy
default:
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
})
return comments
}
-205
View File
@@ -1,205 +0,0 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package engine2
import mock "github.com/stretchr/testify/mock"
import store "github.com/umputun/remark/backend/app/store"
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
// Close provides a mock function with given fields:
func (_m *MockInterface) Close() error {
ret := _m.Called()
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Count provides a mock function with given fields: req
func (_m *MockInterface) Count(req FindRequest) (int, error) {
ret := _m.Called(req)
var r0 int
if rf, ok := ret.Get(0).(func(FindRequest) int); ok {
r0 = rf(req)
} else {
r0 = ret.Get(0).(int)
}
var r1 error
if rf, ok := ret.Get(1).(func(FindRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Create provides a mock function with given fields: comment
func (_m *MockInterface) Create(comment store.Comment) (string, error) {
ret := _m.Called(comment)
var r0 string
if rf, ok := ret.Get(0).(func(store.Comment) string); ok {
r0 = rf(comment)
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Comment) error); ok {
r1 = rf(comment)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Delete provides a mock function with given fields: req
func (_m *MockInterface) Delete(req DeleteRequest) error {
ret := _m.Called(req)
var r0 error
if rf, ok := ret.Get(0).(func(DeleteRequest) error); ok {
r0 = rf(req)
} else {
r0 = ret.Error(0)
}
return r0
}
// Find provides a mock function with given fields: req
func (_m *MockInterface) Find(req FindRequest) ([]store.Comment, error) {
ret := _m.Called(req)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(FindRequest) []store.Comment); ok {
r0 = rf(req)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(FindRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Flag provides a mock function with given fields: req
func (_m *MockInterface) Flag(req FlagRequest) (bool, error) {
ret := _m.Called(req)
var r0 bool
if rf, ok := ret.Get(0).(func(FlagRequest) bool); ok {
r0 = rf(req)
} else {
r0 = ret.Get(0).(bool)
}
var r1 error
if rf, ok := ret.Get(1).(func(FlagRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Get provides a mock function with given fields: locator, commentID
func (_m *MockInterface) Get(locator store.Locator, commentID string) (store.Comment, error) {
ret := _m.Called(locator, commentID)
var r0 store.Comment
if rf, ok := ret.Get(0).(func(store.Locator, string) store.Comment); ok {
r0 = rf(locator, commentID)
} else {
r0 = ret.Get(0).(store.Comment)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator, string) error); ok {
r1 = rf(locator, commentID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Info provides a mock function with given fields: req
func (_m *MockInterface) Info(req InfoRequest) ([]store.PostInfo, error) {
ret := _m.Called(req)
var r0 []store.PostInfo
if rf, ok := ret.Get(0).(func(InfoRequest) []store.PostInfo); ok {
r0 = rf(req)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.PostInfo)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(InfoRequest) error); ok {
r1 = rf(req)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ListFlags provides a mock function with given fields: siteID, flag
func (_m *MockInterface) ListFlags(siteID string, flag Flag) ([]interface{}, error) {
ret := _m.Called(siteID, flag)
var r0 []interface{}
if rf, ok := ret.Get(0).(func(string, Flag) []interface{}); ok {
r0 = rf(siteID, flag)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]interface{})
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, Flag) error); ok {
r1 = rf(siteID, flag)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Update provides a mock function with given fields: locator, comment
func (_m *MockInterface) Update(locator store.Locator, comment store.Comment) error {
ret := _m.Called(locator, comment)
var r0 error
if rf, ok := ret.Get(0).(func(store.Locator, store.Comment) error); ok {
r0 = rf(locator, comment)
} else {
r0 = ret.Error(0)
}
return r0
}
@@ -1,4 +1,4 @@
package engine
package engine_old
import (
"bytes"
@@ -1,4 +1,4 @@
package engine
package engine_old
import (
"fmt"
@@ -1,4 +1,4 @@
package engine
package engine_old
import (
"encoding/json"
@@ -1,4 +1,4 @@
package engine
package engine_old
import (
"testing"
+87
View File
@@ -0,0 +1,87 @@
// Package engine defines interfaces each supported storage should implement.
// Includes default implementation with boltdb
package engine_old
import (
"sort"
"strings"
"time"
"github.com/umputun/remark/backend/app/store"
)
// NOTE: mockery works from linked to go-path and with GOFLAGS='-mod=vendor' go generate
//go:generate sh -c "mockery -inpkg -name Interface -print > /tmp/engine-mock.tmp && mv /tmp/engine-mock.tmp engine_mock.go"
// Interface defines methods provided by low-level storage engine
type Interface interface {
Create(comment store.Comment) (commentID string, err error) // create new comment, avoid dups by id
Get(locator store.Locator, commentID string) (store.Comment, error) // get comment by id
Put(locator store.Locator, comment store.Comment) error // update comment, mutable parts only
Find(locator store.Locator, sort string) ([]store.Comment, error) // find comments for locator
Last(siteID string, limit int, since time.Time) ([]store.Comment, error) // last comments for given site, sorted by time
User(siteID, userID string, limit, skip int) ([]store.Comment, error) // comments by user, sorted by time
UserCount(siteID, userID string) (int, error) // comments count by user
Count(locator store.Locator) (int, error) // number of comments for the post
List(siteID string, limit int, skip int) ([]store.PostInfo, error) // list of commented posts
Info(locator store.Locator, readonlyAge int) (store.PostInfo, error) // get post info
Delete(locator store.Locator, commentID string, mode store.DeleteMode) error // delete comment by id
DeleteAll(siteID string) error // delete all data from site
DeleteUser(siteID string, userID string) error // remove all comments from user
SetBlock(siteID string, userID string, status bool, ttl time.Duration) error // block or unblock user with TTL (0-permanent)
IsBlocked(siteID string, userID string) bool // check if user blocked
Blocked(siteID string) ([]store.BlockedUser, error) // get list of blocked users
SetReadOnly(locator store.Locator, status bool) error // set/reset read-only flag
IsReadOnly(locator store.Locator) bool // check if post read-only
SetVerified(siteID string, userID string, status bool) error // set/reset verified flag
IsVerified(siteID string, userID string) bool // check verified status
Verified(siteID string) ([]string, error) // list of verified user ids
Close() error // close/stop engine
}
const (
// limits
lastLimit = 1000
userLimit = 500
)
// SortComments is for engines can't sort data internally
func SortComments(comments []store.Comment, sortFld string) []store.Comment {
sort.Slice(comments, func(i, j int) bool {
switch sortFld {
case "+time", "-time", "time", "+active", "-active", "active":
if strings.HasPrefix(sortFld, "-") {
return comments[i].Timestamp.After(comments[j].Timestamp)
}
return comments[i].Timestamp.Before(comments[j].Timestamp)
case "+score", "-score", "score":
if strings.HasPrefix(sortFld, "-") {
if comments[i].Score == comments[j].Score {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Score > comments[j].Score
}
if comments[i].Score == comments[j].Score {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Score < comments[j].Score
case "+controversy", "-controversy", "controversy":
if strings.HasPrefix(sortFld, "-") {
if comments[i].Controversy == comments[j].Controversy {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Controversy > comments[j].Controversy
}
if comments[i].Controversy == comments[j].Controversy {
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
return comments[i].Controversy < comments[j].Controversy
default:
return comments[i].Timestamp.Before(comments[j].Timestamp)
}
})
return comments
}
+408
View File
@@ -0,0 +1,408 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package engine_old
import mock "github.com/stretchr/testify/mock"
import store "github.com/umputun/remark/backend/app/store"
import time "time"
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
// Blocked provides a mock function with given fields: siteID
func (_m *MockInterface) Blocked(siteID string) ([]store.BlockedUser, error) {
ret := _m.Called(siteID)
var r0 []store.BlockedUser
if rf, ok := ret.Get(0).(func(string) []store.BlockedUser); ok {
r0 = rf(siteID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.BlockedUser)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(siteID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Close provides a mock function with given fields:
func (_m *MockInterface) Close() error {
ret := _m.Called()
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Count provides a mock function with given fields: locator
func (_m *MockInterface) Count(locator store.Locator) (int, error) {
ret := _m.Called(locator)
var r0 int
if rf, ok := ret.Get(0).(func(store.Locator) int); ok {
r0 = rf(locator)
} else {
r0 = ret.Get(0).(int)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator) error); ok {
r1 = rf(locator)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Create provides a mock function with given fields: comment
func (_m *MockInterface) Create(comment store.Comment) (string, error) {
ret := _m.Called(comment)
var r0 string
if rf, ok := ret.Get(0).(func(store.Comment) string); ok {
r0 = rf(comment)
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Comment) error); ok {
r1 = rf(comment)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Delete provides a mock function with given fields: locator, commentID, mode
func (_m *MockInterface) Delete(locator store.Locator, commentID string, mode store.DeleteMode) error {
ret := _m.Called(locator, commentID, mode)
var r0 error
if rf, ok := ret.Get(0).(func(store.Locator, string, store.DeleteMode) error); ok {
r0 = rf(locator, commentID, mode)
} else {
r0 = ret.Error(0)
}
return r0
}
// DeleteAll provides a mock function with given fields: siteID
func (_m *MockInterface) DeleteAll(siteID string) error {
ret := _m.Called(siteID)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(siteID)
} else {
r0 = ret.Error(0)
}
return r0
}
// DeleteUser provides a mock function with given fields: siteID, userID
func (_m *MockInterface) DeleteUser(siteID string, userID string) error {
ret := _m.Called(siteID, userID)
var r0 error
if rf, ok := ret.Get(0).(func(string, string) error); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Error(0)
}
return r0
}
// Find provides a mock function with given fields: locator, sort
func (_m *MockInterface) Find(locator store.Locator, sort string) ([]store.Comment, error) {
ret := _m.Called(locator, sort)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(store.Locator, string) []store.Comment); ok {
r0 = rf(locator, sort)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator, string) error); ok {
r1 = rf(locator, sort)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Get provides a mock function with given fields: locator, commentID
func (_m *MockInterface) Get(locator store.Locator, commentID string) (store.Comment, error) {
ret := _m.Called(locator, commentID)
var r0 store.Comment
if rf, ok := ret.Get(0).(func(store.Locator, string) store.Comment); ok {
r0 = rf(locator, commentID)
} else {
r0 = ret.Get(0).(store.Comment)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator, string) error); ok {
r1 = rf(locator, commentID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Info provides a mock function with given fields: locator, readonlyAge
func (_m *MockInterface) Info(locator store.Locator, readonlyAge int) (store.PostInfo, error) {
ret := _m.Called(locator, readonlyAge)
var r0 store.PostInfo
if rf, ok := ret.Get(0).(func(store.Locator, int) store.PostInfo); ok {
r0 = rf(locator, readonlyAge)
} else {
r0 = ret.Get(0).(store.PostInfo)
}
var r1 error
if rf, ok := ret.Get(1).(func(store.Locator, int) error); ok {
r1 = rf(locator, readonlyAge)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// IsBlocked provides a mock function with given fields: siteID, userID
func (_m *MockInterface) IsBlocked(siteID string, userID string) bool {
ret := _m.Called(siteID, userID)
var r0 bool
if rf, ok := ret.Get(0).(func(string, string) bool); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// IsReadOnly provides a mock function with given fields: locator
func (_m *MockInterface) IsReadOnly(locator store.Locator) bool {
ret := _m.Called(locator)
var r0 bool
if rf, ok := ret.Get(0).(func(store.Locator) bool); ok {
r0 = rf(locator)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// IsVerified provides a mock function with given fields: siteID, userID
func (_m *MockInterface) IsVerified(siteID string, userID string) bool {
ret := _m.Called(siteID, userID)
var r0 bool
if rf, ok := ret.Get(0).(func(string, string) bool); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// Last provides a mock function with given fields: siteID, limit, since
func (_m *MockInterface) Last(siteID string, limit int, since time.Time) ([]store.Comment, error) {
ret := _m.Called(siteID, limit, since)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(string, int, time.Time) []store.Comment); ok {
r0 = rf(siteID, limit, since)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, int, time.Time) error); ok {
r1 = rf(siteID, limit, since)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// List provides a mock function with given fields: siteID, limit, skip
func (_m *MockInterface) List(siteID string, limit int, skip int) ([]store.PostInfo, error) {
ret := _m.Called(siteID, limit, skip)
var r0 []store.PostInfo
if rf, ok := ret.Get(0).(func(string, int, int) []store.PostInfo); ok {
r0 = rf(siteID, limit, skip)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.PostInfo)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, int, int) error); ok {
r1 = rf(siteID, limit, skip)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Put provides a mock function with given fields: locator, comment
func (_m *MockInterface) Put(locator store.Locator, comment store.Comment) error {
ret := _m.Called(locator, comment)
var r0 error
if rf, ok := ret.Get(0).(func(store.Locator, store.Comment) error); ok {
r0 = rf(locator, comment)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetBlock provides a mock function with given fields: siteID, userID, status, ttl
func (_m *MockInterface) SetBlock(siteID string, userID string, status bool, ttl time.Duration) error {
ret := _m.Called(siteID, userID, status, ttl)
var r0 error
if rf, ok := ret.Get(0).(func(string, string, bool, time.Duration) error); ok {
r0 = rf(siteID, userID, status, ttl)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetReadOnly provides a mock function with given fields: locator, status
func (_m *MockInterface) SetReadOnly(locator store.Locator, status bool) error {
ret := _m.Called(locator, status)
var r0 error
if rf, ok := ret.Get(0).(func(store.Locator, bool) error); ok {
r0 = rf(locator, status)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetVerified provides a mock function with given fields: siteID, userID, status
func (_m *MockInterface) SetVerified(siteID string, userID string, status bool) error {
ret := _m.Called(siteID, userID, status)
var r0 error
if rf, ok := ret.Get(0).(func(string, string, bool) error); ok {
r0 = rf(siteID, userID, status)
} else {
r0 = ret.Error(0)
}
return r0
}
// User provides a mock function with given fields: siteID, userID, limit, skip
func (_m *MockInterface) User(siteID string, userID string, limit int, skip int) ([]store.Comment, error) {
ret := _m.Called(siteID, userID, limit, skip)
var r0 []store.Comment
if rf, ok := ret.Get(0).(func(string, string, int, int) []store.Comment); ok {
r0 = rf(siteID, userID, limit, skip)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]store.Comment)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, int, int) error); ok {
r1 = rf(siteID, userID, limit, skip)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// UserCount provides a mock function with given fields: siteID, userID
func (_m *MockInterface) UserCount(siteID string, userID string) (int, error) {
ret := _m.Called(siteID, userID)
var r0 int
if rf, ok := ret.Get(0).(func(string, string) int); ok {
r0 = rf(siteID, userID)
} else {
r0 = ret.Get(0).(int)
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string) error); ok {
r1 = rf(siteID, userID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Verified provides a mock function with given fields: siteID
func (_m *MockInterface) Verified(siteID string) ([]string, error) {
ret := _m.Called(siteID)
var r0 []string
if rf, ok := ret.Get(0).(func(string) []string); ok {
r0 = rf(siteID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(siteID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
@@ -1,4 +1,4 @@
package engine2
package engine_old
import (
"testing"
@@ -1,4 +1,4 @@
package engine
package engine_old
import (
"time"
@@ -1,4 +1,4 @@
package engine
package engine_old
import (
"fmt"
+32 -33
View File
@@ -19,13 +19,12 @@ import (
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/image"
)
// DataStore wraps store.Interface with additional methods
type DataStore struct {
Engine engine2.Interface
Engine engine.Interface
EditDuration time.Duration
AdminStore admin.Store
MaxCommentSize int
@@ -105,7 +104,7 @@ func (s *DataStore) Create(comment store.Comment) (commentID string, err error)
// Find wraps engine's Find call and alter results if needed
// user used to filter results for self vs others
func (s *DataStore) Find(locator store.Locator, sort string, user store.User) ([]store.Comment, error) {
req := engine2.FindRequest{Locator: locator, Sort: sort}
req := engine.FindRequest{Locator: locator, Sort: sort}
comments, err := s.Engine.Find(req)
if err != nil {
return comments, err
@@ -192,7 +191,7 @@ func (s *DataStore) prepareNewComment(comment store.Comment) (store.Comment, err
// DeleteAll removes all data from site
func (s *DataStore) DeleteAll(siteID string) error {
req := engine2.DeleteRequest{Locator: store.Locator{SiteID: siteID}}
req := engine.DeleteRequest{Locator: store.Locator{SiteID: siteID}}
return s.Engine.Delete(req)
}
@@ -317,7 +316,7 @@ func (s *DataStore) EditComment(locator store.Locator, commentID string, req Edi
if req.Delete { // delete request
comment.Deleted = true
delReq := engine2.DeleteRequest{Locator: locator, CommentID: commentID, DeleteMode: store.SoftDelete}
delReq := engine.DeleteRequest{Locator: locator, CommentID: commentID, DeleteMode: store.SoftDelete}
return comment, s.Engine.Delete(delReq)
}
@@ -351,7 +350,7 @@ func (s *DataStore) HasReplies(comment store.Comment) bool {
return true
}
req := engine2.FindRequest{Locator: store.Locator{SiteID: comment.Locator.SiteID}, Limit: maxLastCommentsReply}
req := engine.FindRequest{Locator: store.Locator{SiteID: comment.Locator.SiteID}, Limit: maxLastCommentsReply}
comments, err := s.Engine.Find(req)
if err != nil {
log.Printf("[WARN] can't get last comments for reply check, %v", err)
@@ -430,7 +429,7 @@ func (s *DataStore) SetTitle(locator store.Locator, commentID string) (comment s
func (s *DataStore) Counts(siteID string, postIDs []string) ([]store.PostInfo, error) {
res := []store.PostInfo{}
for _, p := range postIDs {
req := engine2.FindRequest{Locator: store.Locator{SiteID: siteID, URL: p}}
req := engine.FindRequest{Locator: store.Locator{SiteID: siteID, URL: p}}
if c, err := s.Engine.Count(req); err == nil {
res = append(res, store.PostInfo{URL: p, Count: c})
}
@@ -468,63 +467,63 @@ func (s *DataStore) IsAdmin(siteID string, userID string) bool {
// IsReadOnly checks if post read-only
func (s *DataStore) IsReadOnly(locator store.Locator) bool {
req := engine2.FlagRequest{Locator: locator, Flag: engine2.ReadOnly}
req := engine.FlagRequest{Locator: locator, Flag: engine.ReadOnly}
ro, err := s.Engine.Flag(req)
return err == nil && ro
}
// SetReadOnly set/reset read-only flag
func (s *DataStore) SetReadOnly(locator store.Locator, status bool) error {
roStatus := engine2.FlagFalse
roStatus := engine.FlagFalse
if status {
roStatus = engine2.FlagTrue
roStatus = engine.FlagTrue
}
req := engine2.FlagRequest{Locator: locator, Flag: engine2.ReadOnly, Update: roStatus}
req := engine.FlagRequest{Locator: locator, Flag: engine.ReadOnly, Update: roStatus}
_, err := s.Engine.Flag(req)
return err
}
// IsVerified checks if user verified
func (s *DataStore) IsVerified(siteID string, userID string) bool {
req := engine2.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Flag: engine2.Verified}
req := engine.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Flag: engine.Verified}
ro, err := s.Engine.Flag(req)
return err == nil && ro
}
// SetVerified set/reset verified status for user
func (s *DataStore) SetVerified(siteID string, userID string, status bool) error {
roStatus := engine2.FlagFalse
roStatus := engine.FlagFalse
if status {
roStatus = engine2.FlagTrue
roStatus = engine.FlagTrue
}
req := engine2.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Flag: engine2.Verified, Update: roStatus}
req := engine.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Flag: engine.Verified, Update: roStatus}
_, err := s.Engine.Flag(req)
return err
}
// IsBlocked checks if user blocked
func (s *DataStore) IsBlocked(siteID string, userID string) bool {
req := engine2.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Flag: engine2.Blocked}
req := engine.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Flag: engine.Blocked}
ro, err := s.Engine.Flag(req)
return err == nil && ro
}
// SetBlock set/reset verified status for user
func (s *DataStore) SetBlock(siteID string, userID string, status bool, ttl time.Duration) error {
roStatus := engine2.FlagFalse
roStatus := engine.FlagFalse
if status {
roStatus = engine2.FlagTrue
roStatus = engine.FlagTrue
}
req := engine2.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID,
Flag: engine2.Blocked, Update: roStatus, TTL: ttl}
req := engine.FlagRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID,
Flag: engine.Blocked, Update: roStatus, TTL: ttl}
_, err := s.Engine.Flag(req)
return err
}
// Blocked returns list with all blocked users
func (s *DataStore) Blocked(siteID string) (res []store.BlockedUser, err error) {
blocked, e := s.Engine.ListFlags(siteID, engine2.Blocked)
blocked, e := s.Engine.ListFlags(siteID, engine.Blocked)
if e != nil {
return nil, errors.Wrapf(err, "can't get list of blocked users for %s", siteID)
}
@@ -536,7 +535,7 @@ func (s *DataStore) Blocked(siteID string) (res []store.BlockedUser, err error)
// Info get post info
func (s *DataStore) Info(locator store.Locator, readonlyAge int) (store.PostInfo, error) {
req := engine2.InfoRequest{Locator: locator, ReadOnlyAge: readonlyAge}
req := engine.InfoRequest{Locator: locator, ReadOnlyAge: readonlyAge}
res, err := s.Engine.Info(req)
if err != nil {
return store.PostInfo{}, err
@@ -549,25 +548,25 @@ func (s *DataStore) Info(locator store.Locator, readonlyAge int) (store.PostInfo
// Delete comment by id
func (s *DataStore) Delete(locator store.Locator, commentID string, mode store.DeleteMode) error {
req := engine2.DeleteRequest{Locator: locator, CommentID: commentID, DeleteMode: mode}
req := engine.DeleteRequest{Locator: locator, CommentID: commentID, DeleteMode: mode}
return s.Engine.Delete(req)
}
// DeleteUser removes all comments from user
func (s *DataStore) DeleteUser(siteID string, userID string) error {
req := engine2.DeleteRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, DeleteMode: store.HardDelete}
req := engine.DeleteRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, DeleteMode: store.HardDelete}
return s.Engine.Delete(req)
}
// List of commented posts
func (s *DataStore) List(siteID string, limit int, skip int) ([]store.PostInfo, error) {
req := engine2.InfoRequest{Locator: store.Locator{SiteID: siteID}, Limit: limit, Skip: skip}
req := engine.InfoRequest{Locator: store.Locator{SiteID: siteID}, Limit: limit, Skip: skip}
return s.Engine.Info(req)
}
// Count gets number of comments for the post
func (s *DataStore) Count(locator store.Locator) (int, error) {
req := engine2.FindRequest{Locator: locator}
req := engine.FindRequest{Locator: locator}
return s.Engine.Count(req)
}
@@ -577,7 +576,7 @@ func (s *DataStore) Metas(siteID string) (umetas []UserMetaData, pmetas []PostMe
pmetas = []PostMetaData{}
// set posts meta
posts, err := s.Engine.Info(engine2.InfoRequest{Locator: store.Locator{SiteID: siteID}})
posts, err := s.Engine.Info(engine.InfoRequest{Locator: store.Locator{SiteID: siteID}})
if err != nil {
return nil, nil, errors.Wrapf(err, "can't get list of posts for %s", siteID)
}
@@ -607,7 +606,7 @@ func (s *DataStore) Metas(siteID string) (umetas []UserMetaData, pmetas []PostMe
}
// process verified users
verified, err := s.Engine.ListFlags(siteID, engine2.Verified)
verified, err := s.Engine.ListFlags(siteID, engine.Verified)
if err != nil {
return nil, nil, errors.Wrapf(err, "can't get list of verified users for %s", siteID)
}
@@ -655,7 +654,7 @@ func (s *DataStore) SetMetas(siteID string, umetas []UserMetaData, pmetas []Post
// User gets comment for given userID on siteID
func (s *DataStore) User(siteID, userID string, limit, skip int, user store.User) ([]store.Comment, error) {
req := engine2.FindRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Limit: limit, Skip: skip}
req := engine.FindRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID, Limit: limit, Skip: skip}
comments, err := s.Engine.Find(req)
if err != nil {
return comments, err
@@ -665,13 +664,13 @@ func (s *DataStore) User(siteID, userID string, limit, skip int, user store.User
// UserCount is comments count by user
func (s *DataStore) UserCount(siteID, userID string) (int, error) {
req := engine2.FindRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID}
req := engine.FindRequest{Locator: store.Locator{SiteID: siteID}, UserID: userID}
return s.Engine.Count(req)
}
// Last gets last comments for site, cross-post. Limited by count and optional since ts
func (s *DataStore) Last(siteID string, limit int, since time.Time, user store.User) ([]store.Comment, error) {
req := engine2.FindRequest{Locator: store.Locator{SiteID: siteID}, Limit: limit, Since: since, Sort: "-time"}
req := engine.FindRequest{Locator: store.Locator{SiteID: siteID}, Limit: limit, Since: since, Sort: "-time"}
comments, err := s.Engine.Find(req)
if err != nil {
return comments, err
@@ -720,7 +719,7 @@ func (s *DataStore) alterComments(cc []store.Comment, user store.User) (res []st
func (s *DataStore) alterComment(c store.Comment, user store.User) (res store.Comment) {
blocReq := engine2.FlagRequest{Flag: engine2.Blocked, Locator: store.Locator{SiteID: c.Locator.SiteID}, UserID: c.User.ID}
blocReq := engine.FlagRequest{Flag: engine.Blocked, Locator: store.Locator{SiteID: c.Locator.SiteID}, UserID: c.User.ID}
blocked, _ := s.Engine.Flag(blocReq)
// process blocked users
@@ -734,7 +733,7 @@ func (s *DataStore) alterComment(c store.Comment, user store.User) (res store.Co
// set verified status retroactively
if !blocked {
verifReq := engine2.FlagRequest{Flag: engine2.Verified, Locator: store.Locator{SiteID: c.Locator.SiteID}, UserID: c.User.ID}
verifReq := engine.FlagRequest{Flag: engine.Verified, Locator: store.Locator{SiteID: c.Locator.SiteID}, UserID: c.User.ID}
c.User.Verified, _ = s.Engine.Flag(verifReq)
}
+12 -12
View File
@@ -21,7 +21,7 @@ import (
"github.com/umputun/remark/backend/app/store"
"github.com/umputun/remark/backend/app/store/admin"
"github.com/umputun/remark/backend/app/store/engine2"
"github.com/umputun/remark/backend/app/store/engine"
"github.com/umputun/remark/backend/app/store/image"
)
@@ -1015,9 +1015,9 @@ func TestService_submitImages(t *testing.T) {
func TestService_alterComment(t *testing.T) {
defer teardown(t)
engineMock := engine2.MockInterface{}
engineMock.On("Flag", engine2.FlagRequest{Flag: engine2.Blocked, UserID: "devid"}).Return(false, nil)
engineMock.On("Flag", engine2.FlagRequest{Flag: engine2.Verified, UserID: "devid"}).Return(false, nil)
engineMock := engine.MockInterface{}
engineMock.On("Flag", engine.FlagRequest{Flag: engine.Blocked, UserID: "devid"}).Return(false, nil)
engineMock.On("Flag", engine.FlagRequest{Flag: engine.Verified, UserID: "devid"}).Return(false, nil)
svc := DataStore{Engine: &engineMock}
r := svc.alterComment(store.Comment{ID: "123", User: store.User{IP: "127.0.0.1", ID: "devid"}},
@@ -1027,17 +1027,17 @@ func TestService_alterComment(t *testing.T) {
store.User{Name: "dev", ID: "devid", Admin: true})
assert.Equal(t, store.Comment{ID: "123", User: store.User{IP: "127.0.0.1", ID: "devid"}}, r, "ip not cleaned")
engineMock = engine2.MockInterface{}
engineMock.On("Flag", engine2.FlagRequest{Flag: engine2.Blocked, UserID: "devid"}).Return(false, nil)
engineMock.On("Flag", engine2.FlagRequest{Flag: engine2.Verified, UserID: "devid"}).Return(true, nil)
engineMock = engine.MockInterface{}
engineMock.On("Flag", engine.FlagRequest{Flag: engine.Blocked, UserID: "devid"}).Return(false, nil)
engineMock.On("Flag", engine.FlagRequest{Flag: engine.Verified, UserID: "devid"}).Return(true, nil)
svc = DataStore{Engine: &engineMock}
r = svc.alterComment(store.Comment{ID: "123", User: store.User{IP: "127.0.0.1", ID: "devid", Verified: true}},
store.User{Name: "dev", ID: "devid", Admin: false})
assert.Equal(t, store.Comment{ID: "123", User: store.User{IP: "", ID: "devid", Verified: true}}, r, "verified set")
engineMock = engine2.MockInterface{}
engineMock.On("Flag", engine2.FlagRequest{Flag: engine2.Blocked, UserID: "devid"}).Return(true, nil)
engineMock.On("Flag", engine2.FlagRequest{Flag: engine2.Verified, UserID: "devid"}).Return(false, nil)
engineMock = engine.MockInterface{}
engineMock.On("Flag", engine.FlagRequest{Flag: engine.Blocked, UserID: "devid"}).Return(true, nil)
engineMock.On("Flag", engine.FlagRequest{Flag: engine.Verified, UserID: "devid"}).Return(false, nil)
svc = DataStore{Engine: &engineMock}
r = svc.alterComment(store.Comment{ID: "123", User: store.User{IP: "127.0.0.1", ID: "devid", Verified: true}},
store.User{Name: "dev", ID: "devid", Admin: false})
@@ -1046,10 +1046,10 @@ func TestService_alterComment(t *testing.T) {
}
// makes new boltdb, put two records
func prepStoreEngine(t *testing.T) engine2.Interface {
func prepStoreEngine(t *testing.T) engine.Interface {
_ = os.Remove(testDb)
boltStore, err := engine2.NewBoltDB(bolt.Options{}, engine2.BoltSite{FileName: "/tmp/test-remark.db", SiteID: "radio-t"})
boltStore, err := engine.NewBoltDB(bolt.Options{}, engine.BoltSite{FileName: "/tmp/test-remark.db", SiteID: "radio-t"})
assert.NoError(t, err)
b := boltStore