Files
remark42/backend/app/store/engine/remote.go
T
Dmitry VerkhoturovandGitHub ba7c3aed94 refactor: modernise Go code with go fix and manual improvements (#2027)
Apply go fix ./... analysers (Go 1.26) across backend and examples:
- interface{} → any (type alias, no behaviour change)
- for i := 0; i < N; i++ → for range N / for i := range N
- slices.Contains / slices.ContainsFunc replacing manual loops
- strings.SplitSeq replacing strings.Split in range (avoids allocation)
- strings.CutPrefix replacing HasPrefix+TrimPrefix
- min() replacing manual if/else
- fmt.Appendf replacing []byte(fmt.Sprintf(...))
- strings.Builder replacing string += concatenation
- wg.Go(func(){}) replacing wg.Add(1)/go/wg.Done() pattern
- removed redundant ii := i loop variable copies (unnecessary since Go 1.22)

omitempty on struct-typed JSON fields: go fix removed omitempty from
struct-typed fields (time.Time, PostInfo, UserDetailEntry) because
encoding/json's omitempty never applied to struct types — it was always
a no-op. Kept as bare tags (no omitzero replacement) to preserve the
existing serialisation behaviour.
2026-03-25 16:42:37 -05:00

148 lines
3.6 KiB
Go

package engine
import (
"encoding/json"
"github.com/go-pkgz/jrpc"
"github.com/umputun/remark42/backend/app/store"
)
// RPC implements remote engine and delegates all Calls to remote http server
type RPC struct {
jrpc.Client
}
// Create comment and return ID
func (r *RPC) Create(comment store.Comment) (commentID string, err error) {
resp, err := r.Call("store.create", comment)
if err != nil {
return "", err
}
err = json.Unmarshal(*resp.Result, &commentID)
return commentID, err
}
// Get comment by ID
func (r *RPC) Get(req GetRequest) (comment store.Comment, err error) {
resp, err := r.Call("store.get", req)
if err != nil {
return store.Comment{}, err
}
err = json.Unmarshal(*resp.Result, &comment)
return comment, err
}
// Update comment, mutable parts only
func (r *RPC) Update(comment store.Comment) error {
_, err := r.Call("store.update", comment)
return err
}
// Find comments for locator
func (r *RPC) Find(req FindRequest) (comments []store.Comment, err error) {
resp, err := r.Call("store.find", req)
if err != nil {
return nil, err
}
err = json.Unmarshal(*resp.Result, &comments)
return comments, err
}
// Info returns post(s) meta info
func (r *RPC) Info(req InfoRequest) (info []store.PostInfo, err error) {
resp, err := r.Call("store.info", req)
if err != nil {
return nil, err
}
err = json.Unmarshal(*resp.Result, &info)
return info, err
}
// Flag sets and gets flags
func (r *RPC) Flag(req FlagRequest) (status bool, err error) {
resp, err := r.Call("store.flag", req)
if err != nil {
return false, err
}
err = json.Unmarshal(*resp.Result, &status)
return status, err
}
func unmarshalString(data []byte) ([]any, error) {
var strings []string
if err := json.Unmarshal(data, &strings); err != nil {
return nil, err
}
list := make([]any, 0, len(strings))
for _, w := range strings {
list = append(list, w)
}
return list, nil
}
func unmarshalBlockedUser(data []byte) ([]any, error) {
var blockedUsers []store.BlockedUser
if err := json.Unmarshal(data, &blockedUsers); err != nil {
return nil, err
}
list := make([]any, 0, len(blockedUsers))
for _, w := range blockedUsers {
list = append(list, w)
}
return list, nil
}
// ListFlags get list of flagged keys, like blocked & verified user
func (r *RPC) ListFlags(req FlagRequest) ([]any, error) {
resp, err := r.Call("store.list_flags", req)
if err != nil {
return nil, err
}
// try []store.BlockedUser
list, err := unmarshalBlockedUser(*resp.Result)
if err == nil {
return list, nil
}
// try []strings
return unmarshalString(*resp.Result)
}
// UserDetail sets or gets single detail value, or gets all details for requested site.
// UserDetail returns list even for single entry request is a compromise in order to have both single detail getting and setting
// and all site's details listing under the same function (and not to extend interface by two separate functions).
func (r *RPC) UserDetail(req UserDetailRequest) (result []UserDetailEntry, err error) {
resp, err := r.Call("store.user_detail", req)
if err != nil {
return nil, err
}
err = json.Unmarshal(*resp.Result, &result)
return result, err
}
// Count gets comments count by user or site
func (r *RPC) Count(req FindRequest) (count int, err error) {
resp, err := r.Call("store.count", req)
if err != nil {
return 0, err
}
err = json.Unmarshal(*resp.Result, &count)
return count, err
}
// Delete post(s), user, comment, user details, or everything
func (r *RPC) Delete(req DeleteRequest) error {
_, err := r.Call("store.delete", req)
return err
}
// Close storage engine
func (r *RPC) Close() error {
_, err := r.Call("store.close")
r.Client.Client.CloseIdleConnections()
return err
}