mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-08 05:47:07 +09:00
GO-4459 Merge branch 'main' into GO-4459-rest-api-docs
This commit is contained in:
commit
2cf446429c
126 changed files with 4494 additions and 3196 deletions
34
.github/scripts/is_runner_busy.sh
vendored
Executable file
34
.github/scripts/is_runner_busy.sh
vendored
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
# The script checks whether a runner with a specific label is busy
|
||||
|
||||
OWNER_REPO=$1
|
||||
CHECK_LABELS=$2
|
||||
|
||||
if [[ -z $OWNER_REPO ]]; then
|
||||
cat <<EOF 1>&2
|
||||
Usage: $0 OWNER/REPO CHECK_LABELS
|
||||
|
||||
example: $0 anyproto/test-concurrency "self-hosted ubuntu-latest"
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
EXIT_CODE=0
|
||||
|
||||
# get current runners id
|
||||
# gh api repos/anyproto/test-concurrency/actions/runs --jq '.workflow_runs[] | select(.status!="completed") | {id, name, status, created_at, html_url}'
|
||||
for RUN_ID in $(gh api repos/${OWNER_REPO}/actions/runs --jq '.workflow_runs[] | select(.status!="completed") | .id'); do
|
||||
# get runner_name
|
||||
LABELS=$(gh api repos/${OWNER_REPO}/actions/runs/${RUN_ID}/jobs --jq '[.jobs[].labels[]] | unique | .[]')
|
||||
for CHECK_LABEL in $CHECK_LABELS; do
|
||||
if echo "$LABELS" | grep -q "$CHECK_LABEL"; then
|
||||
echo "A run='$RUN_ID' is executing on a runner with LABEL='$CHECK_LABEL' in the repository='$OWNER_REPO'" 1>&2
|
||||
EXIT_CODE=$(( EXIT_CODE + 1 ))
|
||||
else
|
||||
continue
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
exit $EXIT_CODE
|
19
.github/workflows/build.yml
vendored
19
.github/workflows/build.yml
vendored
|
@ -12,7 +12,7 @@ on:
|
|||
run-on-runner:
|
||||
description: 'Specify the runner to use'
|
||||
required: true
|
||||
default: 'arm64'
|
||||
default: 'mac-mini-org-heart'
|
||||
|
||||
|
||||
permissions:
|
||||
|
@ -22,18 +22,22 @@ permissions:
|
|||
|
||||
|
||||
jobs:
|
||||
wait_for_perftest:
|
||||
uses: ./.github/workflows/reusable_wait_for_perftest.yml
|
||||
|
||||
build:
|
||||
runs-on: ${{ github.event_name == 'push' && 'arm64' || (github.event.inputs.run-on-runner || 'arm64') }}
|
||||
needs: wait_for_perftest
|
||||
runs-on: ${{ github.event_name == 'push' && 'mac-mini-org-heart' || (github.event.inputs.run-on-runner || 'mac-mini-org-heart') }}
|
||||
steps:
|
||||
- name: validate agent
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.run-on-runner }}" != "arm64" ]]; then
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.run-on-runner }}" != "mac-mini-org-heart" ]]; then
|
||||
echo "Invalid runner"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Install Go
|
||||
if: runner.name != 'mac-mini-org-heart'
|
||||
if: ${{ !startsWith(runner.name, 'mac-mini-runner-') }}
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.23.2
|
||||
|
@ -50,9 +54,14 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install brew and node deps
|
||||
if: runner.name != 'mac-mini-org-heart'
|
||||
if: ${{ !startsWith(runner.name, 'mac-mini-runner-') }}
|
||||
run: make install-brew-and-node-deps
|
||||
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: '16.2'
|
||||
|
||||
- name: Set env vars
|
||||
env:
|
||||
UNSPLASH_KEY: ${{ secrets.UNSPLASH_KEY }}
|
||||
|
|
27
.github/workflows/nightly.yml
vendored
27
.github/workflows/nightly.yml
vendored
|
@ -14,12 +14,14 @@ on:
|
|||
options:
|
||||
- alpha
|
||||
- beta
|
||||
# schedule:
|
||||
# - cron: '0 0 * * *' # every day at midnight
|
||||
# filters:
|
||||
# branches:
|
||||
# include:
|
||||
# - 'nightly-ci-test'
|
||||
run-on-runner:
|
||||
description: 'Specify the runner to use'
|
||||
required: true
|
||||
default: 'mac-mini-org-heart'
|
||||
type: choice
|
||||
options:
|
||||
- mac-mini-org-heart
|
||||
- macos-14
|
||||
|
||||
permissions:
|
||||
actions: 'write'
|
||||
|
@ -27,10 +29,15 @@ permissions:
|
|||
contents: 'write'
|
||||
|
||||
jobs:
|
||||
wait_for_perftest:
|
||||
uses: ./.github/workflows/reusable_wait_for_perftest.yml
|
||||
|
||||
build:
|
||||
runs-on: 'macos-14'
|
||||
needs: wait_for_perftest
|
||||
runs-on: ${{ github.event.inputs.run-on-runner }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
if: ${{ !startsWith(runner.name, 'mac-mini-runner-') }}
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.23.2
|
||||
|
@ -47,8 +54,14 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install brew and node deps
|
||||
if: ${{ !startsWith(runner.name, 'mac-mini-runner-') }}
|
||||
run: make install-brew-and-node-deps
|
||||
|
||||
- name: Setup Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: '16.2'
|
||||
|
||||
- name: Nightly mode env settings
|
||||
shell: bash
|
||||
run: |
|
||||
|
|
12
.github/workflows/perftests-grafana.yml
vendored
12
.github/workflows/perftests-grafana.yml
vendored
|
@ -6,7 +6,7 @@ on:
|
|||
run-on-runner:
|
||||
description: 'Specify the runner to use'
|
||||
required: true
|
||||
default: 'arm64'
|
||||
default: 'mac-mini-org-heart'
|
||||
perf-test:
|
||||
description: 'Run perf test times'
|
||||
required: true
|
||||
|
@ -26,11 +26,15 @@ permissions:
|
|||
|
||||
|
||||
jobs:
|
||||
wait_for_self_hosted_mac_mini:
|
||||
uses: ./.github/workflows/reusable_wait_for_self_hosted_mac_mini.yml
|
||||
|
||||
perftests-grafana:
|
||||
runs-on: ${{ github.event.inputs.run-on-runner || 'arm64' }}
|
||||
needs: wait_for_self_hosted_mac_mini
|
||||
runs-on: ${{ github.event.inputs.run-on-runner || 'mac-mini-org-heart' }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
if: runner.name != 'mac-mini-org-heart'
|
||||
if: ${{ !startsWith(runner.name, 'mac-mini-runner-') }}
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.23.2
|
||||
|
@ -47,7 +51,7 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install brew and node deps
|
||||
if: runner.name != 'mac-mini-org-heart'
|
||||
if: ${{ !startsWith(runner.name, 'mac-mini-runner-') }}
|
||||
run: make install-brew-and-node-deps
|
||||
|
||||
- name: Set env vars
|
||||
|
|
8
.github/workflows/perftests.yml
vendored
8
.github/workflows/perftests.yml
vendored
|
@ -8,7 +8,7 @@ on:
|
|||
run-on-runner-mac:
|
||||
description: 'Specify the runner to use on MacOS'
|
||||
required: true
|
||||
default: 'ARM64'
|
||||
default: 'mac-mini-org-heart'
|
||||
run-on-runner-win:
|
||||
description: 'Specify the runner to use on Windows'
|
||||
required: true
|
||||
|
@ -31,9 +31,13 @@ permissions:
|
|||
|
||||
|
||||
jobs:
|
||||
wait_for_self_hosted_mac_mini:
|
||||
uses: ./.github/workflows/reusable_wait_for_self_hosted_mac_mini.yml
|
||||
|
||||
perftests-macos:
|
||||
needs: wait_for_self_hosted_mac_mini
|
||||
timeout-minutes: 60
|
||||
runs-on: 'ARM64'
|
||||
runs-on: 'mac-mini-org-heart'
|
||||
steps:
|
||||
- name: Setup GO
|
||||
run: |
|
||||
|
|
22
.github/workflows/reusable_wait_for_perftest.yml
vendored
Normal file
22
.github/workflows/reusable_wait_for_perftest.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
name: Reusable Workflow wait for perftests to finish
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
wait_for_perftest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Wait for perftests to finish
|
||||
run: |
|
||||
while true; do
|
||||
RUNNING=$(gh run list --repo $GITHUB_REPOSITORY --workflow perftests.yml --workflow perftests-grafana.yml --status in_progress --json status --jq 'length')
|
||||
if [[ "$RUNNING" -eq 0 ]]; then
|
||||
echo "perftests is finished, proceeding with build."
|
||||
break
|
||||
fi
|
||||
echo "perftests is still running. Waiting 10 seconds..."
|
||||
sleep 10
|
||||
done
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
26
.github/workflows/reusable_wait_for_self_hosted_mac_mini.yml
vendored
Normal file
26
.github/workflows/reusable_wait_for_self_hosted_mac_mini.yml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
name: Reusable Workflow wait for self-hosted mac mini is free
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
wait_for_self_hosted_mac_mini:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Wait for self-hosted runners to be free
|
||||
run: |
|
||||
while true; do
|
||||
if .github/scripts/is_runner_busy.sh $GITHUB_REPOSITORY mac-mini-org-heart; then
|
||||
echo "self-hosted runner 'mac-mini-org-heart' is free"
|
||||
break
|
||||
else
|
||||
echo "self-hosted runner 'mac-mini-org-heart' is busy. waiting 10 seconds..."
|
||||
sleep 10
|
||||
continue
|
||||
fi
|
||||
done
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
@ -16,7 +16,11 @@ permissions:
|
|||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
wait_for_perftest:
|
||||
uses: ./.github/workflows/reusable_wait_for_perftest.yml
|
||||
|
||||
unit-test:
|
||||
needs: wait_for_perftest
|
||||
runs-on: ${{ vars.RUNNER_TEST }}
|
||||
env:
|
||||
GOPRIVATE: github.com/anyproto
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -20,3 +20,4 @@ build
|
|||
/core/anytype/config/nodes/custom.yml
|
||||
/.direnv/
|
||||
/.envrc
|
||||
*.swp
|
||||
|
|
|
@ -53,6 +53,7 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatal("can't import the tree:", err)
|
||||
}
|
||||
defer res.Store.Close()
|
||||
objectTree, err := res.CreateReadableTree(*fromRoot, "")
|
||||
if err != nil {
|
||||
log.Fatal("can't create readable tree:", err)
|
||||
|
|
|
@ -306,7 +306,7 @@ func getTableSizes(mw *core.Middleware) (tables map[string]uint64) {
|
|||
tables = make(map[string]uint64)
|
||||
cfg := mw.GetApp().MustComponent(config.CName).(*config.Config)
|
||||
|
||||
db, err := sql.Open("sqlite3", cfg.GetSqliteStorePath())
|
||||
db, err := sql.Open("sqlite3", cfg.GetNewSpaceStorePath())
|
||||
if err != nil {
|
||||
fmt.Println("Error opening database:", err)
|
||||
return
|
||||
|
|
|
@ -47,17 +47,21 @@ type (
|
|||
}
|
||||
|
||||
useCaseInfo struct {
|
||||
objects map[string]objectInfo
|
||||
relations map[string]domain.RelationKey
|
||||
types map[string]domain.TypeKey
|
||||
templates map[string]string
|
||||
options map[string]domain.RelationKey
|
||||
files []string
|
||||
objects map[string]objectInfo
|
||||
relations map[string]domain.RelationKey
|
||||
types map[string]domain.TypeKey
|
||||
templates map[string]string
|
||||
options map[string]domain.RelationKey
|
||||
fileObjects []string
|
||||
|
||||
// big data
|
||||
files map[string][]byte
|
||||
snapshots map[string]*pb.SnapshotWithType
|
||||
profile []byte
|
||||
|
||||
customTypesAndRelations map[string]customInfo
|
||||
|
||||
useCase string
|
||||
profileFileFound bool
|
||||
useCase string
|
||||
}
|
||||
|
||||
cliFlags struct {
|
||||
|
@ -68,12 +72,14 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
func (i customInfo) GetFormat() model.RelationFormat {
|
||||
return i.relationFormat
|
||||
}
|
||||
|
||||
func (f cliFlags) isUpdateNeeded() bool {
|
||||
return f.analytics || f.creator || f.removeRelations || f.exclude || f.rules != ""
|
||||
}
|
||||
|
||||
const anytypeProfileFilename = addr.AnytypeProfileId + ".pb"
|
||||
|
||||
var (
|
||||
errIncorrectFileFound = fmt.Errorf("incorrect protobuf file was found")
|
||||
errValidationFailed = fmt.Errorf("validation failed")
|
||||
|
@ -111,7 +117,7 @@ func run() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.profileFileFound {
|
||||
if info.profile == nil {
|
||||
fmt.Println("profile file does not present in archive")
|
||||
}
|
||||
|
||||
|
@ -129,7 +135,7 @@ func run() error {
|
|||
defer writer.Close()
|
||||
}
|
||||
|
||||
err = processFiles(r.File, writer, info, flags, updateNeeded)
|
||||
err = processFiles(info, writer, flags)
|
||||
|
||||
if flags.list {
|
||||
listObjects(info)
|
||||
|
@ -199,17 +205,13 @@ func collectUseCaseInfo(files []*zip.File, fileName string) (info *useCaseInfo,
|
|||
types: make(map[string]domain.TypeKey, len(files)-1),
|
||||
templates: make(map[string]string),
|
||||
options: make(map[string]domain.RelationKey),
|
||||
files: make([]string, 0),
|
||||
files: make(map[string][]byte),
|
||||
snapshots: make(map[string]*pb.SnapshotWithType, len(files)),
|
||||
fileObjects: make([]string, 0),
|
||||
customTypesAndRelations: make(map[string]customInfo),
|
||||
profileFileFound: false,
|
||||
}
|
||||
for _, f := range files {
|
||||
if f.Name == constant.ProfileFile {
|
||||
info.profileFileFound = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (strings.HasPrefix(f.Name, export.Files) && !strings.HasPrefix(f.Name, export.FilesObjects)) || f.FileInfo().IsDir() {
|
||||
if f.FileInfo().IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -218,7 +220,17 @@ func collectUseCaseInfo(files []*zip.File, fileName string) (info *useCaseInfo,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
snapshot, _, err := extractSnapshotAndType(data, f.Name)
|
||||
if isPlainFile(f.Name) {
|
||||
info.files[f.Name] = data
|
||||
continue
|
||||
}
|
||||
|
||||
if f.Name == constant.ProfileFile {
|
||||
info.profile = data
|
||||
continue
|
||||
}
|
||||
|
||||
snapshot, err := extractSnapshotAndType(data, f.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract snapshot from file %s: %w", f.Name, err)
|
||||
}
|
||||
|
@ -232,6 +244,8 @@ func collectUseCaseInfo(files []*zip.File, fileName string) (info *useCaseInfo,
|
|||
SbType: smartblock.SmartBlockType(snapshot.SbType),
|
||||
}
|
||||
|
||||
info.snapshots[f.Name] = snapshot
|
||||
|
||||
switch snapshot.SbType {
|
||||
case model.SmartBlockType_STRelation:
|
||||
uk := pbtypes.GetString(snapshot.Snapshot.Data.Details, bundle.RelationKeyUniqueKey.String())
|
||||
|
@ -268,7 +282,7 @@ func collectUseCaseInfo(files []*zip.File, fileName string) (info *useCaseInfo,
|
|||
case model.SmartBlockType_STRelationOption:
|
||||
info.options[id] = domain.RelationKey(pbtypes.GetString(snapshot.Snapshot.Data.Details, bundle.RelationKeyRelationKey.String()))
|
||||
case model.SmartBlockType_FileObject:
|
||||
info.files = append(info.files, id)
|
||||
info.fileObjects = append(info.fileObjects, id)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -287,46 +301,47 @@ func readData(f *zip.File) ([]byte, error) {
|
|||
return data, nil
|
||||
}
|
||||
|
||||
func processFiles(files []*zip.File, zw *zip.Writer, info *useCaseInfo, flags *cliFlags, writeNewFile bool) error {
|
||||
var incorrectFileFound bool
|
||||
for _, f := range files {
|
||||
if f.Name == anytypeProfileFilename {
|
||||
fmt.Println(anytypeProfileFilename, "is excluded")
|
||||
continue
|
||||
}
|
||||
data, err := readData(f)
|
||||
func processFiles(info *useCaseInfo, zw *zip.Writer, flags *cliFlags) error {
|
||||
var (
|
||||
incorrectFileFound bool
|
||||
writeNewFile = flags.isUpdateNeeded()
|
||||
)
|
||||
|
||||
if info.profile != nil {
|
||||
data, err := processProfile(info, flags.spaceDashboardId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newData []byte
|
||||
if f.FileInfo().IsDir() {
|
||||
newData = data
|
||||
} else {
|
||||
newData, err = processRawData(data, f.Name, info, flags)
|
||||
if err != nil {
|
||||
if !(flags.exclude && errors.Is(err, errValidationFailed)) {
|
||||
// just do not include object that failed validation
|
||||
incorrectFileFound = true
|
||||
}
|
||||
continue
|
||||
if writeNewFile {
|
||||
if err = saveDataToZip(zw, constant.ProfileFile, data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if writeNewFile {
|
||||
for name, data := range info.files {
|
||||
if err := saveDataToZip(zw, name, data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for name, sn := range info.snapshots {
|
||||
newData, err := processSnapshot(sn, info, flags)
|
||||
if err != nil {
|
||||
if !(flags.exclude && errors.Is(err, errValidationFailed)) {
|
||||
// just do not include object that failed validation
|
||||
incorrectFileFound = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if newData == nil || !writeNewFile {
|
||||
continue
|
||||
}
|
||||
newFileName := f.Name
|
||||
if strings.HasSuffix(newFileName, ".pb.json") {
|
||||
// output of usecase validator is always an archive with protobufs
|
||||
newFileName = strings.TrimSuffix(newFileName, ".json")
|
||||
}
|
||||
nf, err := zw.Create(newFileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create new file %s: %w", newFileName, err)
|
||||
}
|
||||
if _, err = io.Copy(nf, bytes.NewReader(newData)); err != nil {
|
||||
return fmt.Errorf("failed to copy snapshot to new file %s: %w", newFileName, err)
|
||||
if err = saveDataToZip(zw, name, newData); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,38 +351,40 @@ func processFiles(files []*zip.File, zw *zip.Writer, info *useCaseInfo, flags *c
|
|||
return nil
|
||||
}
|
||||
|
||||
func processRawData(data []byte, name string, info *useCaseInfo, flags *cliFlags) ([]byte, error) {
|
||||
if name == constant.ProfileFile {
|
||||
return processProfile(data, info, flags.spaceDashboardId)
|
||||
func saveDataToZip(zw *zip.Writer, fileName string, data []byte) error {
|
||||
if strings.HasSuffix(fileName, ".pb.json") {
|
||||
// output of usecase validator is always an archive with protobufs
|
||||
fileName = strings.TrimSuffix(fileName, ".json")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, "files") {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
snapshot, isOldAccount, err := extractSnapshotAndType(data, name)
|
||||
nf, err := zw.Create(fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return fmt.Errorf("failed to create new file %s: %w", fileName, err)
|
||||
}
|
||||
if _, err = io.Copy(nf, bytes.NewReader(data)); err != nil {
|
||||
return fmt.Errorf("failed to copy snapshot to new file %s: %w", fileName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processSnapshot(s *pb.SnapshotWithType, info *useCaseInfo, flags *cliFlags) ([]byte, error) {
|
||||
if flags.analytics {
|
||||
insertAnalyticsData(snapshot.Snapshot, info)
|
||||
insertAnalyticsData(s.Snapshot, info)
|
||||
}
|
||||
|
||||
if flags.removeRelations {
|
||||
removeAccountRelatedDetails(snapshot.Snapshot)
|
||||
removeAccountRelatedDetails(s.Snapshot)
|
||||
}
|
||||
|
||||
if flags.creator {
|
||||
insertCreatorInfo(snapshot.Snapshot)
|
||||
insertCreatorInfo(s.Snapshot)
|
||||
}
|
||||
|
||||
if flags.rules != "" {
|
||||
processRules(snapshot.Snapshot)
|
||||
processRules(s.Snapshot)
|
||||
}
|
||||
|
||||
if flags.validate {
|
||||
if err = validate(snapshot, info); err != nil {
|
||||
if err := validate(s, info); err != nil {
|
||||
if errors.Is(err, errSkipObject) {
|
||||
// some validators register errors mentioning that object can be excluded
|
||||
return nil, nil
|
||||
|
@ -378,51 +395,49 @@ func processRawData(data []byte, name string, info *useCaseInfo, flags *cliFlags
|
|||
}
|
||||
|
||||
if flags.collectCustomUsageInfo {
|
||||
collectCustomObjectsUsageInfo(snapshot, info)
|
||||
collectCustomObjectsUsageInfo(s, info)
|
||||
}
|
||||
|
||||
if isOldAccount {
|
||||
return snapshot.Snapshot.Marshal()
|
||||
if s.SbType == model.SmartBlockType_AccountOld {
|
||||
return s.Snapshot.Marshal()
|
||||
}
|
||||
|
||||
return snapshot.Marshal()
|
||||
return s.Marshal()
|
||||
}
|
||||
|
||||
func extractSnapshotAndType(data []byte, name string) (s *pb.SnapshotWithType, isOldAccount bool, err error) {
|
||||
func extractSnapshotAndType(data []byte, name string) (s *pb.SnapshotWithType, err error) {
|
||||
s = &pb.SnapshotWithType{}
|
||||
if strings.HasSuffix(name, ".json") {
|
||||
if err = jsonpb.UnmarshalString(string(data), s); err != nil {
|
||||
return nil, false, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
return nil, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
}
|
||||
if s.SbType == model.SmartBlockType_AccountOld {
|
||||
cs := &pb.ChangeSnapshot{}
|
||||
isOldAccount = true
|
||||
if err = jsonpb.UnmarshalString(string(data), cs); err != nil {
|
||||
return nil, false, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
return nil, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
}
|
||||
s = &pb.SnapshotWithType{
|
||||
Snapshot: cs,
|
||||
SbType: model.SmartBlockType_Page,
|
||||
SbType: model.SmartBlockType_AccountOld,
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.Unmarshal(data); err != nil {
|
||||
return nil, false, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
return nil, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
}
|
||||
if s.SbType == model.SmartBlockType_AccountOld {
|
||||
cs := &pb.ChangeSnapshot{}
|
||||
isOldAccount = true
|
||||
if err = cs.Unmarshal(data); err != nil {
|
||||
return nil, false, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
return nil, fmt.Errorf("cannot unmarshal snapshot from file %s: %w", name, err)
|
||||
}
|
||||
s = &pb.SnapshotWithType{
|
||||
Snapshot: cs,
|
||||
SbType: model.SmartBlockType_Page,
|
||||
SbType: model.SmartBlockType_AccountOld,
|
||||
}
|
||||
}
|
||||
return s, isOldAccount, nil
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func validate(snapshot *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
||||
|
@ -478,7 +493,8 @@ func removeAccountRelatedDetails(s *pb.ChangeSnapshot) {
|
|||
bundle.RelationKeyAddedDate.String(),
|
||||
bundle.RelationKeySyncDate.String(),
|
||||
bundle.RelationKeySyncError.String(),
|
||||
bundle.RelationKeySyncStatus.String():
|
||||
bundle.RelationKeySyncStatus.String(),
|
||||
bundle.RelationKeyChatId.String():
|
||||
|
||||
delete(s.Data.Details.Fields, key)
|
||||
}
|
||||
|
@ -490,9 +506,9 @@ func insertCreatorInfo(s *pb.ChangeSnapshot) {
|
|||
s.Data.Details.Fields[bundle.RelationKeyLastModifiedBy.String()] = pbtypes.String(addr.AnytypeProfileId)
|
||||
}
|
||||
|
||||
func processProfile(data []byte, info *useCaseInfo, spaceDashboardId string) ([]byte, error) {
|
||||
func processProfile(info *useCaseInfo, spaceDashboardId string) ([]byte, error) {
|
||||
profile := &pb.Profile{}
|
||||
if err := profile.Unmarshal(data); err != nil {
|
||||
if err := profile.Unmarshal(info.profile); err != nil {
|
||||
e := fmt.Errorf("cannot unmarshal profile: %w", err)
|
||||
fmt.Println(e)
|
||||
return nil, e
|
||||
|
@ -564,8 +580,12 @@ func listObjects(info *useCaseInfo) {
|
|||
|
||||
fmt.Println("\n- File Objects:")
|
||||
fmt.Println("Id: " + strings.Repeat(" ", 31) + "Name")
|
||||
for _, id := range info.files {
|
||||
for _, id := range info.fileObjects {
|
||||
obj := info.objects[id]
|
||||
fmt.Printf("%s:\t%32s\n", id[len(id)-4:], obj.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func isPlainFile(name string) bool {
|
||||
return strings.HasPrefix(name, export.Files) && !strings.HasPrefix(name, export.FilesObjects)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,10 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/samber/lo"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/widget"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
|
@ -32,7 +31,6 @@ type keyWithIndex struct {
|
|||
}
|
||||
|
||||
var validators = []validator{
|
||||
validateRelationLinks,
|
||||
validateRelationBlocks,
|
||||
validateDetails,
|
||||
validateObjectTypes,
|
||||
|
@ -41,26 +39,6 @@ var validators = []validator{
|
|||
validateRelationOption,
|
||||
}
|
||||
|
||||
func validateRelationLinks(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
||||
id := pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
linksToDelete := make([]keyWithIndex, 0)
|
||||
for i, rel := range s.Snapshot.Data.RelationLinks {
|
||||
if bundle.HasRelation(domain.RelationKey(rel.Key)) {
|
||||
continue
|
||||
}
|
||||
if _, found := info.customTypesAndRelations[rel.Key]; found {
|
||||
continue
|
||||
}
|
||||
linksToDelete = append([]keyWithIndex{{key: rel.Key, index: i}}, linksToDelete...)
|
||||
|
||||
}
|
||||
for _, link := range linksToDelete {
|
||||
fmt.Println("WARNING: object", id, "contains link to unknown relation:", link.key, ", so it was deleted from snapshot")
|
||||
s.Snapshot.Data.RelationLinks = append(s.Snapshot.Data.RelationLinks[:link.index], s.Snapshot.Data.RelationLinks[link.index+1:]...)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func validateRelationBlocks(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
||||
id := pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
var relKeys []string
|
||||
|
@ -105,16 +83,10 @@ func validateDetails(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
|||
)
|
||||
rel, e = bundle.GetRelation(domain.RelationKey(k))
|
||||
if e != nil {
|
||||
rel = getRelationLinkByKey(s.Snapshot.Data.RelationLinks, k)
|
||||
if rel == nil {
|
||||
if relation, errFound := bundle.GetRelation(domain.RelationKey(k)); errFound == nil {
|
||||
s.Snapshot.Data.RelationLinks = append(s.Snapshot.Data.RelationLinks, &model.RelationLink{
|
||||
Key: k,
|
||||
Format: relation.Format,
|
||||
})
|
||||
continue
|
||||
}
|
||||
err = multierror.Append(err, fmt.Errorf("relation '%s' exists in details of object '%s', but not in relation links", k, id))
|
||||
var found bool
|
||||
rel, found = info.customTypesAndRelations[k]
|
||||
if !found {
|
||||
err = multierror.Append(err, fmt.Errorf("relation '%s' exists in details of object '%s', but not in the archive", k, id))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +94,12 @@ func validateDetails(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
|||
continue
|
||||
}
|
||||
|
||||
values := pbtypes.GetStringListValue(v)
|
||||
var (
|
||||
values = pbtypes.GetStringListValue(v)
|
||||
isUpdateNeeded bool
|
||||
newValues = make([]string, 0, len(values))
|
||||
)
|
||||
|
||||
for _, val := range values {
|
||||
if bundle.HasRelation(domain.RelationKey(strings.TrimPrefix(val, addr.RelationKeyToIdPrefix))) ||
|
||||
bundle.HasObjectTypeByKey(domain.TypeKey(strings.TrimPrefix(val, addr.ObjectTypeKeyToIdPrefix))) || val == addr.AnytypeProfileId {
|
||||
|
@ -135,15 +112,31 @@ func validateDetails(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if k == bundle.RelationKeySpaceDashboardId.String() && val == "lastOpened" {
|
||||
continue
|
||||
}
|
||||
|
||||
_, found := info.objects[val]
|
||||
if !found {
|
||||
if isBrokenTemplate(k, val) {
|
||||
fmt.Println("WARNING: object", id, "is a template with no target type included in the archive, so it will be skipped")
|
||||
return errSkipObject
|
||||
}
|
||||
if isRecommendedRelationsKey(k) {
|
||||
// we can exclude recommended relations that are not found, because the majority of types are not imported
|
||||
fmt.Println("WARNING: type", id, "contains relation", val, "that is not included in the archive, so this relation will be excluded from the list")
|
||||
isUpdateNeeded = true
|
||||
continue
|
||||
}
|
||||
err = multierror.Append(err, fmt.Errorf("failed to find target id for detail '%s: %s' of object %s", k, val, id))
|
||||
} else {
|
||||
newValues = append(newValues, val)
|
||||
}
|
||||
}
|
||||
|
||||
if isUpdateNeeded {
|
||||
s.Snapshot.Data.Details.Fields[k] = pbtypes.StringList(newValues)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -162,14 +155,22 @@ func validateObjectTypes(s *pb.SnapshotWithType, info *useCaseInfo) (err error)
|
|||
}
|
||||
|
||||
func validateBlockLinks(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
||||
id := pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
var (
|
||||
id = pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
widgetLinkBlocksToDelete []string
|
||||
)
|
||||
|
||||
for _, b := range s.Snapshot.Data.Blocks {
|
||||
switch a := simple.New(b).(type) {
|
||||
case link.Block:
|
||||
target := a.Model().GetLink().TargetBlockId
|
||||
_, found := info.objects[target]
|
||||
if !found {
|
||||
if s.SbType == model.SmartBlockType_Widget && isDefaultWidget(target) {
|
||||
if s.SbType == model.SmartBlockType_Widget {
|
||||
if isDefaultWidget(target) {
|
||||
continue
|
||||
}
|
||||
widgetLinkBlocksToDelete = append(widgetLinkBlocksToDelete, b.Id)
|
||||
continue
|
||||
}
|
||||
err = multierror.Append(err, fmt.Errorf("failed to find target id for link '%s' in block '%s' of object '%s'",
|
||||
|
@ -206,39 +207,10 @@ func validateBlockLinks(s *pb.SnapshotWithType, info *useCaseInfo) (err error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err == nil && len(widgetLinkBlocksToDelete) > 0 {
|
||||
err = removeWidgetBlocks(s, id, widgetLinkBlocksToDelete)
|
||||
}
|
||||
|
||||
func validateFileKeys(s *pb.SnapshotWithType, _ *useCaseInfo) (err error) {
|
||||
id := pbtypes.GetString(s.Snapshot.Data.Details, bundle.RelationKeyId.String())
|
||||
for _, r := range s.Snapshot.Data.RelationLinks {
|
||||
if r.Format == model.RelationFormat_file || r.Key == bundle.RelationKeyCoverId.String() {
|
||||
for _, hash := range pbtypes.GetStringList(s.Snapshot.GetData().GetDetails(), r.Key) {
|
||||
if r.Format != model.RelationFormat_file {
|
||||
_, err := cid.Parse(hash)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !snapshotHasKeyForHash(s, hash) {
|
||||
err = multierror.Append(err, fmt.Errorf("object '%s' has file detail '%s' has hash '%s' which keys are not in the snapshot", id, r.Key, hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, b := range s.Snapshot.Data.Blocks {
|
||||
if v, ok := simple.New(b).(simple.FileHashes); ok {
|
||||
hashes := v.FillFileHashes([]string{})
|
||||
if len(hashes) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, hash := range hashes {
|
||||
if !snapshotHasKeyForHash(s, hash) {
|
||||
err = multierror.Append(err, fmt.Errorf("file block '%s' of object '%s' has hash '%s' which keys are not in the snapshot", b.Id, id, hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -299,8 +271,14 @@ func snapshotHasKeyForHash(s *pb.SnapshotWithType, hash string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// these relations will be overwritten on import
|
||||
func isLinkRelation(k string) bool {
|
||||
return k == bundle.RelationKeyLinks.String() || k == bundle.RelationKeySourceObject.String() || k == bundle.RelationKeyBacklinks.String()
|
||||
return slices.Contains([]string{
|
||||
bundle.RelationKeyLinks.String(),
|
||||
bundle.RelationKeySourceObject.String(),
|
||||
bundle.RelationKeyBacklinks.String(),
|
||||
bundle.RelationKeyMentions.String(),
|
||||
}, k)
|
||||
}
|
||||
|
||||
func canRelationContainObjectValues(format model.RelationFormat) bool {
|
||||
|
@ -316,10 +294,11 @@ func canRelationContainObjectValues(format model.RelationFormat) bool {
|
|||
}
|
||||
|
||||
func isDefaultWidget(target string) bool {
|
||||
return lo.Contains([]string{
|
||||
return slices.Contains([]string{
|
||||
widget.DefaultWidgetFavorite,
|
||||
widget.DefaultWidgetSet,
|
||||
widget.DefaultWidgetRecent,
|
||||
widget.DefaultWidgetRecentOpen,
|
||||
widget.DefaultWidgetCollection,
|
||||
}, target)
|
||||
}
|
||||
|
@ -327,3 +306,56 @@ func isDefaultWidget(target string) bool {
|
|||
func isBrokenTemplate(key, value string) bool {
|
||||
return key == bundle.RelationKeyTargetObjectType.String() && value == addr.MissingObject
|
||||
}
|
||||
|
||||
func isRecommendedRelationsKey(key string) bool {
|
||||
return slices.Contains([]string{
|
||||
bundle.RelationKeyRecommendedRelations.String(),
|
||||
bundle.RelationKeyRecommendedFeaturedRelations.String(),
|
||||
bundle.RelationKeyRecommendedHiddenRelations.String(),
|
||||
bundle.RelationKeyRecommendedFileRelations.String(),
|
||||
}, key)
|
||||
}
|
||||
|
||||
// removeWidgetBlocks removes link blocks and widget blocks from Widget object.
|
||||
// For each link block we should remove parent widget block and remove its id from root's children.
|
||||
// Widget object blocks structure:
|
||||
//
|
||||
// root
|
||||
// |--- widget1
|
||||
// | |--- link1
|
||||
// |
|
||||
// |--- widget2
|
||||
// |--- link2
|
||||
func removeWidgetBlocks(s *pb.SnapshotWithType, rootId string, linkBlockIds []string) error {
|
||||
widgetBlockIds := make([]string, 0, len(linkBlockIds))
|
||||
var rootBlock *model.Block
|
||||
|
||||
for _, b := range s.Snapshot.Data.Blocks {
|
||||
if b.Id == rootId {
|
||||
rootBlock = b
|
||||
continue
|
||||
}
|
||||
// widget block has only one child - link block
|
||||
if len(b.ChildrenIds) != 1 {
|
||||
continue
|
||||
}
|
||||
if slices.Contains(linkBlockIds, b.ChildrenIds[0]) {
|
||||
widgetBlockIds = append(widgetBlockIds, b.Id)
|
||||
}
|
||||
}
|
||||
|
||||
if rootBlock == nil {
|
||||
return fmt.Errorf("root block not found")
|
||||
}
|
||||
|
||||
rootBlock.ChildrenIds = slices.DeleteFunc(rootBlock.ChildrenIds, func(id string) bool {
|
||||
return slices.Contains(widgetBlockIds, id)
|
||||
})
|
||||
|
||||
blocksToDelete := slices.Concat(widgetBlockIds, linkBlockIds)
|
||||
s.Snapshot.Data.Blocks = slices.DeleteFunc(s.Snapshot.Data.Blocks, func(b *model.Block) bool {
|
||||
return slices.Contains(blocksToDelete, b.Id)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
153
cmd/usecasevalidator/validators_test.go
Normal file
153
cmd/usecasevalidator/validators_test.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
//go:build !nogrpcserver && !_test
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
func TestValidateDetails(t *testing.T) {
|
||||
t.Run("snapshot is valid", func(t *testing.T) {
|
||||
// given
|
||||
s := &pb.SnapshotWithType{Snapshot: &pb.ChangeSnapshot{Data: &model.SmartBlockSnapshotBase{
|
||||
Details: &types.Struct{Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyName.String(): pbtypes.String("snap shot"),
|
||||
bundle.RelationKeyType.String(): pbtypes.String(bundle.TypeKeyTask.URL()),
|
||||
bundle.RelationKeyAssignee.String(): pbtypes.String("kirill"),
|
||||
bundle.RelationKeyTasks.String(): pbtypes.StringList([]string{"task1", "task2"}),
|
||||
bundle.RelationKeyFeaturedRelations.String(): pbtypes.StringList([]string{
|
||||
bundle.RelationKeyType.URL(), "rel-customTag",
|
||||
}),
|
||||
}},
|
||||
}}}
|
||||
info := &useCaseInfo{
|
||||
objects: map[string]objectInfo{
|
||||
bundle.TypeKeyTask.URL(): {},
|
||||
"kirill": {},
|
||||
"task1": {},
|
||||
"task2": {},
|
||||
},
|
||||
customTypesAndRelations: map[string]customInfo{
|
||||
"rel-customTag": {},
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
err := validateDetails(s, info)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("some object is missing", func(t *testing.T) {
|
||||
// given
|
||||
s := &pb.SnapshotWithType{Snapshot: &pb.ChangeSnapshot{Data: &model.SmartBlockSnapshotBase{
|
||||
Details: &types.Struct{Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyAssignee.String(): pbtypes.String("kirill"),
|
||||
}},
|
||||
}}}
|
||||
info := &useCaseInfo{}
|
||||
|
||||
// when
|
||||
err := validateDetails(s, info)
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("broken template", func(t *testing.T) {
|
||||
// given
|
||||
s := &pb.SnapshotWithType{Snapshot: &pb.ChangeSnapshot{Data: &model.SmartBlockSnapshotBase{
|
||||
Details: &types.Struct{Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyTargetObjectType.String(): pbtypes.String(addr.MissingObject),
|
||||
}},
|
||||
}}}
|
||||
info := &useCaseInfo{}
|
||||
|
||||
// when
|
||||
err := validateDetails(s, info)
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, errSkipObject, err)
|
||||
})
|
||||
|
||||
t.Run("exclude missing recommendedRelations", func(t *testing.T) {
|
||||
// given
|
||||
s := &pb.SnapshotWithType{Snapshot: &pb.ChangeSnapshot{Data: &model.SmartBlockSnapshotBase{
|
||||
Details: &types.Struct{Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyRecommendedRelations.String(): pbtypes.StringList([]string{
|
||||
bundle.RelationKeyCreator.BundledURL(),
|
||||
bundle.RelationKeyCreatedDate.BundledURL(),
|
||||
}),
|
||||
bundle.RelationKeyRecommendedFeaturedRelations.String(): pbtypes.StringList([]string{
|
||||
bundle.RelationKeyType.BundledURL(),
|
||||
bundle.RelationKeyTag.BundledURL(),
|
||||
}),
|
||||
}},
|
||||
}}}
|
||||
info := &useCaseInfo{
|
||||
objects: map[string]objectInfo{
|
||||
bundle.RelationKeyCreator.BundledURL(): {},
|
||||
bundle.RelationKeyTag.BundledURL(): {},
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
err := validateDetails(s, info)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{bundle.RelationKeyCreator.BundledURL()}, pbtypes.GetStringList(s.Snapshot.Data.Details, bundle.RelationKeyRecommendedRelations.String()))
|
||||
assert.Equal(t, []string{bundle.RelationKeyTag.BundledURL()}, pbtypes.GetStringList(s.Snapshot.Data.Details, bundle.RelationKeyRecommendedFeaturedRelations.String()))
|
||||
})
|
||||
}
|
||||
|
||||
func TestRemoveWidgetBlock(t *testing.T) {
|
||||
rootId := "root"
|
||||
t.Run("blocks were removed", func(t *testing.T) {
|
||||
// given
|
||||
s := &pb.SnapshotWithType{Snapshot: &pb.ChangeSnapshot{Data: &model.SmartBlockSnapshotBase{
|
||||
Blocks: []*model.Block{
|
||||
{Id: rootId, ChildrenIds: []string{"w1", "w2", "w3"}},
|
||||
{Id: "w1", ChildrenIds: []string{"l1"}},
|
||||
{Id: "w2", ChildrenIds: []string{"l2"}},
|
||||
{Id: "w3", ChildrenIds: []string{"l3"}},
|
||||
{Id: "l1"}, {Id: "l2"}, {Id: "l3"},
|
||||
},
|
||||
}}}
|
||||
|
||||
// when
|
||||
err := removeWidgetBlocks(s, rootId, []string{"l2", "l3"})
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, s.Snapshot.Data.Blocks, 3)
|
||||
assert.Equal(t, []string{"w1"}, s.Snapshot.Data.Blocks[0].ChildrenIds)
|
||||
})
|
||||
|
||||
t.Run("no root found", func(t *testing.T) {
|
||||
// given
|
||||
s := &pb.SnapshotWithType{Snapshot: &pb.ChangeSnapshot{Data: &model.SmartBlockSnapshotBase{
|
||||
Blocks: []*model.Block{
|
||||
{Id: "wrong root id", ChildrenIds: []string{"w1"}},
|
||||
{Id: "w1", ChildrenIds: []string{"l1"}}, {Id: "l1"},
|
||||
},
|
||||
}}}
|
||||
|
||||
// when
|
||||
err := removeWidgetBlocks(s, rootId, []string{"l1"})
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
|
@ -150,6 +150,7 @@ func (s *service) GetInfo(ctx context.Context) (*model.AccountInfo, error) {
|
|||
AnalyticsId: analyticsId,
|
||||
NetworkId: s.getNetworkId(),
|
||||
TechSpaceId: s.spaceService.TechSpaceId(),
|
||||
EthereumAddress: s.wallet.GetAccountEthAddress().Hex(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -136,8 +136,8 @@ func BootstrapConfig(newAccount bool, isStaging bool) *config.Config {
|
|||
)
|
||||
}
|
||||
|
||||
func BootstrapWallet(rootPath string, derivationResult crypto.DerivationResult) wallet.Wallet {
|
||||
return wallet.NewWithAccountRepo(rootPath, derivationResult)
|
||||
func BootstrapWallet(rootPath string, derivationResult crypto.DerivationResult, lang string) wallet.Wallet {
|
||||
return wallet.NewWithAccountRepo(rootPath, derivationResult, lang)
|
||||
}
|
||||
|
||||
func StartNewApp(ctx context.Context, clientWithVersion string, components ...app.Component) (a *app.App, err error) {
|
||||
|
@ -157,14 +157,8 @@ func StartNewApp(ctx context.Context, clientWithVersion string, components ...ap
|
|||
totalSpent := time.Since(startTime)
|
||||
l := log.With(zap.Int64("total", totalSpent.Milliseconds()))
|
||||
stat := a.StartStat()
|
||||
event := &metrics.AppStart{
|
||||
TotalMs: stat.SpentMsTotal,
|
||||
PerCompMs: stat.SpentMsPerComp,
|
||||
Extra: map[string]interface{}{},
|
||||
}
|
||||
|
||||
if v, ok := ctx.Value(metrics.CtxKeyRPC).(string); ok {
|
||||
event.Request = v
|
||||
l = l.With(zap.String("rpc", v))
|
||||
}
|
||||
|
||||
|
@ -181,19 +175,10 @@ func StartNewApp(ctx context.Context, clientWithVersion string, components ...ap
|
|||
for _, field := range c.GetLogFields() {
|
||||
field.Key = comp.Name() + "_" + field.Key
|
||||
l = l.With(field)
|
||||
if field.String != "" {
|
||||
event.Extra[field.Key] = field.String
|
||||
} else {
|
||||
event.Extra[field.Key] = field.Integer
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if metrics.Enabled {
|
||||
metrics.Service.Send(event)
|
||||
}
|
||||
if totalSpent > WarningAfter {
|
||||
l.Warn("app started")
|
||||
} else {
|
||||
|
|
|
@ -194,7 +194,7 @@ func (c *Config) initFromFileAndEnv(repoPath string) error {
|
|||
if len(split) == 1 {
|
||||
return fmt.Errorf("failed to split repo path: %s", repoPath)
|
||||
}
|
||||
c.SqliteTempPath = filepath.Join(split[0], "cache")
|
||||
c.SqliteTempPath = filepath.Join(split[0], "files")
|
||||
c.AnyStoreConfig.SQLiteConnectionOptions = make(map[string]string)
|
||||
c.AnyStoreConfig.SQLiteConnectionOptions["temp_store_directory"] = "'" + c.SqliteTempPath + "'"
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ func (s *Service) AccountCreate(ctx context.Context, req *pb.RpcAccountCreateReq
|
|||
}
|
||||
comps := []app.Component{
|
||||
cfg,
|
||||
anytype.BootstrapWallet(s.rootPath, derivationResult),
|
||||
anytype.BootstrapWallet(s.rootPath, derivationResult, s.fulltextPrimaryLanguage),
|
||||
s.eventSender,
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ func (s *Service) RecoverFromLegacy(req *pb.RpcAccountRecoverFromLegacyExportReq
|
|||
return RecoverFromLegacyResponse{}, ErrAccountMismatch
|
||||
}
|
||||
s.rootPath = req.RootPath
|
||||
s.fulltextPrimaryLanguage = req.FulltextPrimaryLanguage
|
||||
err = os.MkdirAll(s.rootPath, 0700)
|
||||
if err != nil {
|
||||
return RecoverFromLegacyResponse{}, anyerror.CleanupError(err)
|
||||
|
@ -134,7 +135,7 @@ func (s *Service) RecoverFromLegacy(req *pb.RpcAccountRecoverFromLegacyExportReq
|
|||
func (s *Service) startApp(cfg *config.Config, derivationResult crypto.DerivationResult) error {
|
||||
comps := []app.Component{
|
||||
cfg,
|
||||
anytype.BootstrapWallet(s.rootPath, derivationResult),
|
||||
anytype.BootstrapWallet(s.rootPath, derivationResult, s.fulltextPrimaryLanguage),
|
||||
s.eventSender,
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ func (s *Service) AccountSelect(ctx context.Context, req *pb.RpcAccountSelectReq
|
|||
if req.Id == "" {
|
||||
return nil, ErrEmptyAccountID
|
||||
}
|
||||
curMigration := s.migrationManager.getOrCreateMigration(req.RootPath, req.Id)
|
||||
curMigration := s.migrationManager.getOrCreateMigration(req.RootPath, req.Id, req.FulltextPrimaryLanguage)
|
||||
if !curMigration.successful() {
|
||||
return nil, ErrAccountStoreIsNotMigrated
|
||||
}
|
||||
|
@ -82,16 +82,30 @@ func (s *Service) AccountSelect(ctx context.Context, req *pb.RpcAccountSelectReq
|
|||
}
|
||||
metrics.Service.SetWorkingDir(req.RootPath, req.Id)
|
||||
|
||||
return s.start(ctx, req.Id, req.RootPath, req.DisableLocalNetworkSync, req.JsonApiListenAddr, req.PreferYamuxTransport, req.NetworkMode, req.NetworkCustomConfigFilePath)
|
||||
return s.start(ctx, req.Id, req.RootPath, req.DisableLocalNetworkSync, req.JsonApiListenAddr,
|
||||
req.PreferYamuxTransport, req.NetworkMode, req.NetworkCustomConfigFilePath, req.FulltextPrimaryLanguage)
|
||||
}
|
||||
|
||||
func (s *Service) start(ctx context.Context, id string, rootPath string, disableLocalNetworkSync bool, jsonApiListenAddr string, preferYamux bool, networkMode pb.RpcAccountNetworkMode, networkConfigFilePath string) (*model.Account, error) {
|
||||
func (s *Service) start(
|
||||
ctx context.Context,
|
||||
id string,
|
||||
rootPath string,
|
||||
disableLocalNetworkSync bool,
|
||||
jsonApiListenAddr string,
|
||||
preferYamux bool,
|
||||
networkMode pb.RpcAccountNetworkMode,
|
||||
networkConfigFilePath string,
|
||||
lang string,
|
||||
) (*model.Account, error) {
|
||||
ctx, task := trace2.NewTask(ctx, "application.start")
|
||||
defer task.End()
|
||||
|
||||
if rootPath != "" {
|
||||
s.rootPath = rootPath
|
||||
}
|
||||
if lang != "" {
|
||||
s.fulltextPrimaryLanguage = lang
|
||||
}
|
||||
if s.mnemonic == "" {
|
||||
return nil, ErrNoMnemonicProvided
|
||||
}
|
||||
|
@ -129,7 +143,7 @@ func (s *Service) start(ctx context.Context, id string, rootPath string, disable
|
|||
}
|
||||
comps := []app.Component{
|
||||
cfg,
|
||||
anytype.BootstrapWallet(s.rootPath, res),
|
||||
anytype.BootstrapWallet(s.rootPath, res, s.fulltextPrimaryLanguage),
|
||||
s.eventSender,
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ func (s *Service) AccountChangeNetworkConfigAndRestart(ctx context.Context, req
|
|||
}
|
||||
|
||||
rootPath := s.app.MustComponent(walletComp.CName).(walletComp.Wallet).RootPath()
|
||||
lang := s.app.MustComponent(walletComp.CName).(walletComp.Wallet).FtsPrimaryLang()
|
||||
accountId := s.app.MustComponent(walletComp.CName).(walletComp.Wallet).GetAccountPrivkey().GetPublic().Account()
|
||||
conf := s.app.MustComponent(config.CName).(*config.Config)
|
||||
|
||||
|
@ -89,7 +90,8 @@ func (s *Service) AccountChangeNetworkConfigAndRestart(ctx context.Context, req
|
|||
return ErrFailedToStopApplication
|
||||
}
|
||||
|
||||
_, err = s.start(ctx, accountId, rootPath, conf.DontStartLocalNetworkSyncAutomatically, conf.JsonApiListenAddr, conf.PeferYamuxTransport, req.NetworkMode, req.NetworkCustomConfigFilePath)
|
||||
_, err = s.start(ctx, accountId, rootPath, conf.DontStartLocalNetworkSyncAutomatically, conf.JsonApiListenAddr,
|
||||
conf.PeferYamuxTransport, req.NetworkMode, req.NetworkCustomConfigFilePath, lang)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ func (s *Service) AccountMigrate(ctx context.Context, req *pb.RpcAccountMigrateR
|
|||
if s.rootPath == "" {
|
||||
s.rootPath = req.RootPath
|
||||
}
|
||||
return s.migrationManager.getOrCreateMigration(req.RootPath, req.Id).wait()
|
||||
return s.migrationManager.getOrCreateMigration(req.RootPath, req.Id, req.FulltextPrimaryLanguage).wait()
|
||||
}
|
||||
|
||||
func (s *Service) AccountMigrateCancel(ctx context.Context, req *pb.RpcAccountMigrateCancelRequest) error {
|
||||
|
@ -37,7 +37,7 @@ func (s *Service) AccountMigrateCancel(ctx context.Context, req *pb.RpcAccountMi
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) migrate(ctx context.Context, id string) error {
|
||||
func (s *Service) migrate(ctx context.Context, id, lang string) error {
|
||||
res, err := core.WalletAccountAt(s.mnemonic, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -53,7 +53,7 @@ func (s *Service) migrate(ctx context.Context, id string) error {
|
|||
cfg.DisableNetworkIdCheck = true
|
||||
comps := []app.Component{
|
||||
cfg,
|
||||
anytype.BootstrapWallet(s.rootPath, res),
|
||||
anytype.BootstrapWallet(s.rootPath, res, lang),
|
||||
s.eventSender,
|
||||
}
|
||||
a := &app.App{}
|
||||
|
@ -75,21 +75,23 @@ type migration struct {
|
|||
err error
|
||||
id string
|
||||
done chan struct{}
|
||||
lang string
|
||||
}
|
||||
|
||||
func newMigration(m *migrationManager, id string) *migration {
|
||||
func newMigration(m *migrationManager, id, lang string) *migration {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &migration{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
done: make(chan struct{}),
|
||||
id: id,
|
||||
lang: lang,
|
||||
manager: m,
|
||||
}
|
||||
}
|
||||
|
||||
func newSuccessfulMigration(manager *migrationManager, id string) *migration {
|
||||
m := newMigration(manager, id)
|
||||
func newSuccessfulMigration(manager *migrationManager, id, lang string) *migration {
|
||||
m := newMigration(manager, id, lang)
|
||||
m.setFinished(nil, false)
|
||||
return m
|
||||
}
|
||||
|
@ -127,7 +129,7 @@ func (m *migration) wait() error {
|
|||
return m.err
|
||||
}
|
||||
m.mx.Unlock()
|
||||
err := m.manager.service.migrate(m.ctx, m.id)
|
||||
err := m.manager.service.migrate(m.ctx, m.id, m.lang)
|
||||
if err != nil {
|
||||
m.setFinished(err, true)
|
||||
return err
|
||||
|
@ -184,7 +186,7 @@ func (m *migrationManager) isRunning() bool {
|
|||
return m.runningMigration != ""
|
||||
}
|
||||
|
||||
func (m *migrationManager) getOrCreateMigration(rootPath, id string) *migration {
|
||||
func (m *migrationManager) getOrCreateMigration(rootPath, id, lang string) *migration {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
if m.migrations == nil {
|
||||
|
@ -194,14 +196,14 @@ func (m *migrationManager) getOrCreateMigration(rootPath, id string) *migration
|
|||
sqlitePath := filepath.Join(rootPath, id, config.SpaceStoreSqlitePath)
|
||||
baderPath := filepath.Join(rootPath, id, config.SpaceStoreBadgerPath)
|
||||
if anyPathExists([]string{sqlitePath, baderPath}) {
|
||||
m.migrations[id] = newMigration(m, id)
|
||||
m.migrations[id] = newMigration(m, id, lang)
|
||||
} else {
|
||||
m.migrations[id] = newSuccessfulMigration(m, id)
|
||||
m.migrations[id] = newSuccessfulMigration(m, id, lang)
|
||||
}
|
||||
}
|
||||
if m.migrations[id].finished() && !m.migrations[id].successful() {
|
||||
// resetting migration
|
||||
m.migrations[id] = newMigration(m, id)
|
||||
m.migrations[id] = newMigration(m, id, lang)
|
||||
}
|
||||
return m.migrations[id]
|
||||
}
|
||||
|
|
|
@ -25,12 +25,13 @@ type Service struct {
|
|||
// memoized private key derived from mnemonic, used for signing session tokens
|
||||
sessionSigningKey []byte
|
||||
|
||||
rootPath string
|
||||
clientWithVersion string
|
||||
eventSender event.Sender
|
||||
sessions session.Service
|
||||
traceRecorder *traceRecorder
|
||||
migrationManager *migrationManager
|
||||
rootPath string
|
||||
fulltextPrimaryLanguage string
|
||||
clientWithVersion string
|
||||
eventSender event.Sender
|
||||
sessions session.Service
|
||||
traceRecorder *traceRecorder
|
||||
migrationManager *migrationManager
|
||||
|
||||
appAccountStartInProcessCancel context.CancelFunc
|
||||
appAccountStartInProcessCancelMutex sync.Mutex
|
||||
|
|
|
@ -17,6 +17,7 @@ func (s *Service) WalletCreate(req *pb.RpcWalletCreateRequest) (string, error) {
|
|||
defer s.lock.Unlock()
|
||||
|
||||
s.rootPath = req.RootPath
|
||||
s.fulltextPrimaryLanguage = req.FulltextPrimaryLanguage
|
||||
|
||||
err := os.MkdirAll(s.rootPath, 0700)
|
||||
if err != nil {
|
||||
|
|
|
@ -32,5 +32,6 @@ func (s *Service) WalletRecover(req *pb.RpcWalletRecoverRequest) error {
|
|||
return err
|
||||
}
|
||||
s.rootPath = req.RootPath
|
||||
s.fulltextPrimaryLanguage = req.FulltextPrimaryLanguage
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -208,7 +208,6 @@ func (a *accountObject) initState(st *state.State) error {
|
|||
template.InitTemplate(st,
|
||||
template.WithTitle,
|
||||
template.WithForcedObjectTypes([]domain.TypeKey{bundle.TypeKeyProfile}),
|
||||
template.WithResolvedLayout(model.ObjectType_profile),
|
||||
template.WithLayout(model.ObjectType_profile),
|
||||
template.WithDetail(bundle.RelationKeyLayoutAlign, domain.Int64(model.Block_AlignCenter)),
|
||||
)
|
||||
|
|
|
@ -260,8 +260,7 @@ func (bs *basic) setDetailSpecialCases(st *state.State, detail domain.Detail) er
|
|||
return fmt.Errorf("can't change object type directly: %w", domain.ErrValidationFailed)
|
||||
}
|
||||
if detail.Key == bundle.RelationKeyResolvedLayout {
|
||||
// special case when client sets the layout detail directly instead of using SetLayoutInState command
|
||||
return bs.SetLayoutInState(st, model.ObjectTypeLayout(detail.Value.Int64()), false)
|
||||
return fmt.Errorf("can't change object layout directly: %w", domain.ErrValidationFailed)
|
||||
}
|
||||
if detail.Key == bundle.RelationKeyRecommendedLayout {
|
||||
// nolint:gosec
|
||||
|
@ -380,7 +379,7 @@ func (bs *basic) SetLayoutInState(s *state.State, toLayout model.ObjectTypeLayou
|
|||
return fmt.Errorf("layout change is restricted for object '%s': %w", bs.Id(), err)
|
||||
}
|
||||
}
|
||||
s.SetDetail(bundle.RelationKeyResolvedLayout, domain.Int64(toLayout))
|
||||
|
||||
if err = bs.layoutConverter.Convert(s, fromLayout, toLayout, ignoreRestriction); err != nil {
|
||||
return fmt.Errorf("convert layout: %w", err)
|
||||
}
|
||||
|
|
|
@ -1109,7 +1109,7 @@ func addDescription(st *smarttest.SmartTest, description string) {
|
|||
func addRelations(st *smarttest.SmartTest) {
|
||||
newState := st.Doc.NewState()
|
||||
template.InitTemplate(newState, template.RequireHeader)
|
||||
template.InitTemplate(newState, template.WithFeaturedRelations)
|
||||
template.InitTemplate(newState, template.WithFeaturedRelationsBlock)
|
||||
template.InitTemplate(newState, template.WithForcedDescription)
|
||||
state.ApplyState("", newState, false)
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ func isPageLayout(layout model.ObjectTypeLayout) bool {
|
|||
model.ObjectType_todo,
|
||||
model.ObjectType_note,
|
||||
model.ObjectType_profile,
|
||||
model.ObjectType_bookmark,
|
||||
}, layout)
|
||||
}
|
||||
|
||||
|
|
|
@ -218,3 +218,16 @@ func TestInsertGroupRelationKey(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLayout_isConversionAllowed(t *testing.T) {
|
||||
lc := layoutConverter{}
|
||||
assert.True(t, lc.isConversionAllowed(model.ObjectType_basic, model.ObjectType_todo))
|
||||
assert.True(t, lc.isConversionAllowed(model.ObjectType_profile, model.ObjectType_note))
|
||||
assert.True(t, lc.isConversionAllowed(model.ObjectType_basic, model.ObjectType_bookmark))
|
||||
assert.True(t, lc.isConversionAllowed(model.ObjectType_bookmark, model.ObjectType_note))
|
||||
assert.True(t, lc.isConversionAllowed(model.ObjectType_set, model.ObjectType_collection))
|
||||
assert.False(t, lc.isConversionAllowed(model.ObjectType_collection, model.ObjectType_set))
|
||||
assert.False(t, lc.isConversionAllowed(model.ObjectType_set, model.ObjectType_basic))
|
||||
assert.False(t, lc.isConversionAllowed(model.ObjectType_todo, model.ObjectType_collection))
|
||||
assert.False(t, lc.isConversionAllowed(model.ObjectType_basic, model.ObjectType_relation))
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ func (p *Dashboard) CreationStateMigration(ctx *smartblock.InitContext) migratio
|
|||
template.InitTemplate(st,
|
||||
template.WithObjectTypes([]domain.TypeKey{bundle.TypeKeyDashboard}),
|
||||
template.WithLayout(model.ObjectType_dashboard),
|
||||
template.WithResolvedLayout(model.ObjectType_dashboard),
|
||||
template.WithEmpty,
|
||||
template.WithDetailName("Home"),
|
||||
template.WithDetailIconEmoji("🏠"),
|
||||
|
|
|
@ -176,11 +176,12 @@ func (f *ObjectFactory) New(space smartblock.Space, sbType coresb.SmartBlockType
|
|||
coresb.SmartBlockTypeDate,
|
||||
coresb.SmartBlockTypeBundledRelation,
|
||||
coresb.SmartBlockTypeBundledObjectType,
|
||||
coresb.SmartBlockTypeObjectType,
|
||||
coresb.SmartBlockTypeRelation,
|
||||
coresb.SmartBlockTypeRelationOption,
|
||||
coresb.SmartBlockTypeChatObject:
|
||||
return f.newPage(space.Id(), sb), nil
|
||||
case coresb.SmartBlockTypeObjectType:
|
||||
return f.newObjectType(space.Id(), sb), nil
|
||||
case coresb.SmartBlockTypeArchive:
|
||||
return NewArchive(sb, store), nil
|
||||
case coresb.SmartBlockTypeHome:
|
||||
|
|
447
core/block/editor/objecttype.go
Normal file
447
core/block/editor/objecttype.go
Normal file
|
@ -0,0 +1,447 @@
|
|||
package editor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/anyproto/any-sync/app/ocache"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/basic"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/clipboard"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/dataview"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/file"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/stext"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/template"
|
||||
"github.com/anyproto/anytype-heart/core/block/migration"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/block/source"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/relationutils"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/database"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/spaceindex"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
var typeRequiredRelations = append(typeAndRelationRequiredRelations,
|
||||
bundle.RelationKeyRecommendedRelations,
|
||||
bundle.RelationKeyRecommendedFeaturedRelations,
|
||||
bundle.RelationKeyRecommendedHiddenRelations,
|
||||
bundle.RelationKeyRecommendedFileRelations,
|
||||
bundle.RelationKeyRecommendedLayout,
|
||||
bundle.RelationKeySmartblockTypes,
|
||||
bundle.RelationKeyIconOption,
|
||||
bundle.RelationKeyIconName,
|
||||
)
|
||||
|
||||
type ObjectType struct {
|
||||
smartblock.SmartBlock
|
||||
basic.AllOperations
|
||||
basic.IHistory
|
||||
stext.Text
|
||||
clipboard.Clipboard
|
||||
source.ChangeReceiver
|
||||
dataview.Dataview
|
||||
|
||||
spaceIndex spaceindex.Store
|
||||
}
|
||||
|
||||
func (f *ObjectFactory) newObjectType(spaceId string, sb smartblock.SmartBlock) *ObjectType {
|
||||
store := f.objectStore.SpaceIndex(spaceId)
|
||||
fileComponent := file.NewFile(sb, f.fileBlockService, f.picker, f.processService, f.fileUploaderService)
|
||||
return &ObjectType{
|
||||
SmartBlock: sb,
|
||||
ChangeReceiver: sb.(source.ChangeReceiver),
|
||||
AllOperations: basic.NewBasic(sb, store, f.layoutConverter, f.fileObjectService),
|
||||
IHistory: basic.NewHistory(sb),
|
||||
Text: stext.NewText(
|
||||
sb,
|
||||
store,
|
||||
f.eventSender,
|
||||
),
|
||||
Clipboard: clipboard.NewClipboard(
|
||||
sb,
|
||||
fileComponent,
|
||||
f.tempDirProvider,
|
||||
store,
|
||||
f.fileService,
|
||||
f.fileObjectService,
|
||||
),
|
||||
Dataview: dataview.NewDataview(sb, store),
|
||||
|
||||
spaceIndex: store,
|
||||
}
|
||||
}
|
||||
|
||||
func (ot *ObjectType) Init(ctx *smartblock.InitContext) (err error) {
|
||||
ctx.RequiredInternalRelationKeys = append(ctx.RequiredInternalRelationKeys, typeRequiredRelations...)
|
||||
|
||||
if err = ot.SmartBlock.Init(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ot.AddHook(ot.syncLayoutForObjectsAndTemplates, smartblock.HookAfterApply)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ot *ObjectType) CreationStateMigration(ctx *smartblock.InitContext) migration.Migration {
|
||||
return migration.Migration{
|
||||
Version: 2,
|
||||
Proc: func(s *state.State) {
|
||||
if len(ctx.ObjectTypeKeys) > 0 && len(ctx.State.ObjectTypeKeys()) == 0 {
|
||||
ctx.State.SetObjectTypeKeys(ctx.ObjectTypeKeys)
|
||||
}
|
||||
|
||||
templates := []template.StateTransformer{
|
||||
template.WithEmpty,
|
||||
template.WithObjectTypes(ctx.State.ObjectTypeKeys()),
|
||||
template.WithTitle,
|
||||
template.WithLayout(model.ObjectType_objectType),
|
||||
}
|
||||
|
||||
template.InitTemplate(s, templates...)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (ot *ObjectType) StateMigrations() migration.Migrations {
|
||||
return migration.MakeMigrations([]migration.Migration{
|
||||
{
|
||||
Version: 2,
|
||||
Proc: func(s *state.State) {},
|
||||
},
|
||||
{
|
||||
Version: 3,
|
||||
Proc: ot.featuredRelationsMigration,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (ot *ObjectType) featuredRelationsMigration(s *state.State) {
|
||||
if ot.Type() != coresb.SmartBlockTypeObjectType {
|
||||
return
|
||||
}
|
||||
|
||||
if s.HasRelation(bundle.RelationKeyRecommendedFeaturedRelations.String()) {
|
||||
return
|
||||
}
|
||||
|
||||
var typeKey domain.TypeKey
|
||||
if uk, err := domain.UnmarshalUniqueKey(s.Details().GetString(bundle.RelationKeyUniqueKey)); err == nil {
|
||||
typeKey = domain.TypeKey(uk.InternalKey())
|
||||
}
|
||||
|
||||
featuredRelationKeys := relationutils.DefaultFeaturedRelationKeys(typeKey)
|
||||
featuredRelationIds := make([]string, 0, len(featuredRelationKeys))
|
||||
for _, key := range featuredRelationKeys {
|
||||
id, err := ot.Space().DeriveObjectID(context.Background(), domain.MustUniqueKey(coresb.SmartBlockTypeRelation, key.String()))
|
||||
if err != nil {
|
||||
log.Errorf("failed to derive object id: %v", err)
|
||||
continue
|
||||
}
|
||||
featuredRelationIds = append(featuredRelationIds, id)
|
||||
}
|
||||
|
||||
if len(featuredRelationIds) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
s.SetDetail(bundle.RelationKeyRecommendedFeaturedRelations, domain.StringList(featuredRelationIds))
|
||||
|
||||
recommendedRelations := s.Details().GetStringList(bundle.RelationKeyRecommendedRelations)
|
||||
oldLen := len(recommendedRelations)
|
||||
recommendedRelations = slices.DeleteFunc(recommendedRelations, func(s string) bool {
|
||||
return slices.Contains(featuredRelationIds, s)
|
||||
})
|
||||
|
||||
if oldLen == len(recommendedRelations) {
|
||||
return
|
||||
}
|
||||
|
||||
s.SetDetail(bundle.RelationKeyRecommendedRelations, domain.StringList(recommendedRelations))
|
||||
}
|
||||
|
||||
type layoutState struct {
|
||||
layout int64
|
||||
layoutAlign int64
|
||||
featuredRelations []string
|
||||
|
||||
isLayoutSet bool
|
||||
isLayoutAlignSet bool
|
||||
isFeaturedRelationsSet bool
|
||||
}
|
||||
|
||||
func (ls layoutState) isAllSet() bool {
|
||||
return ls.isLayoutSet && ls.isLayoutAlignSet && ls.isFeaturedRelationsSet
|
||||
}
|
||||
|
||||
func (ls layoutState) isAnySet() bool {
|
||||
return ls.isLayoutSet || ls.isLayoutAlignSet || ls.isFeaturedRelationsSet
|
||||
}
|
||||
|
||||
type relationIdDeriver struct {
|
||||
space smartblock.Space
|
||||
cache map[domain.RelationKey]string
|
||||
}
|
||||
|
||||
func (d *relationIdDeriver) deriveId(key domain.RelationKey) (string, error) {
|
||||
if d.cache != nil {
|
||||
if id, found := d.cache[key]; found {
|
||||
return id, nil
|
||||
}
|
||||
}
|
||||
|
||||
id, err := d.space.DeriveObjectID(context.Background(), domain.MustUniqueKey(coresb.SmartBlockTypeRelation, key.String()))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to derive relation id: %w", err)
|
||||
}
|
||||
|
||||
if d.cache == nil {
|
||||
d.cache = map[domain.RelationKey]string{}
|
||||
}
|
||||
d.cache[key] = id
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (ot *ObjectType) syncLayoutForObjectsAndTemplates(info smartblock.ApplyInfo) error {
|
||||
newLayout := getLayoutStateFromMessages(info.Events)
|
||||
if newLayout.isLayoutSet && !isLayoutChangeApplicable(newLayout.layout) {
|
||||
// if layout change is not applicable, then it is init of some system type. Objects' layout should not be modified
|
||||
newLayout.isLayoutSet = false
|
||||
}
|
||||
|
||||
if !newLayout.isAnySet() {
|
||||
// layout details were not changed
|
||||
return nil
|
||||
}
|
||||
|
||||
oldLayout := getLayoutStateFromParent(info.ParentState)
|
||||
|
||||
records, err := ot.queryObjectsAndTemplates()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
resultErr error
|
||||
deriver = relationIdDeriver{space: ot.Space()}
|
||||
)
|
||||
|
||||
for _, record := range records {
|
||||
id := record.Details.GetString(bundle.RelationKeyId)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
changes := collectRelationsChanges(record.Details, newLayout, oldLayout, deriver)
|
||||
if len(changes.relationsToRemove) > 0 || changes.isFeaturedRelationsChanged {
|
||||
// we should modify not local relations from object, that's why we apply changes even if object is not in cache
|
||||
err = ot.Space().Do(id, func(b smartblock.SmartBlock) error {
|
||||
st := b.NewState()
|
||||
st.RemoveDetail(changes.relationsToRemove...)
|
||||
if changes.isFeaturedRelationsChanged {
|
||||
st.SetDetail(bundle.RelationKeyFeaturedRelations, domain.StringList(changes.newFeaturedRelations))
|
||||
}
|
||||
return b.Apply(st)
|
||||
})
|
||||
if err != nil {
|
||||
resultErr = errors.Join(resultErr, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if changes.isLayoutFound || !newLayout.isLayoutSet || record.Details.GetInt64(bundle.RelationKeyResolvedLayout) == newLayout.layout {
|
||||
// layout detail remains in object or recommendedLayout was not changed or relevant layout is already set, skipping
|
||||
continue
|
||||
}
|
||||
|
||||
err = ot.Space().DoLockedIfNotExists(id, func() error {
|
||||
return ot.spaceIndex.ModifyObjectDetails(id, func(details *domain.Details) (*domain.Details, bool, error) {
|
||||
if details == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
if details.GetInt64(bundle.RelationKeyResolvedLayout) == newLayout.layout {
|
||||
return nil, false, nil
|
||||
}
|
||||
details.Set(bundle.RelationKeyResolvedLayout, domain.Int64(newLayout.layout))
|
||||
return details, true, nil
|
||||
})
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if !errors.Is(err, ocache.ErrExists) {
|
||||
resultErr = errors.Join(resultErr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = ot.Space().Do(id, func(b smartblock.SmartBlock) error {
|
||||
if cr, ok := b.(source.ChangeReceiver); ok {
|
||||
// we can do StateAppend here, so resolvedLayout will be injected automatically
|
||||
return cr.StateAppend(func(d state.Doc) (s *state.State, changes []*pb.ChangeContent, err error) {
|
||||
return d.NewState(), nil, nil
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
resultErr = errors.Join(resultErr, err)
|
||||
}
|
||||
}
|
||||
|
||||
if resultErr != nil {
|
||||
return fmt.Errorf("failed to change layout details for objects: %w", resultErr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isLayoutChangeApplicable(layout int64) bool {
|
||||
return slices.Contains([]model.ObjectTypeLayout{
|
||||
model.ObjectType_basic,
|
||||
model.ObjectType_todo,
|
||||
model.ObjectType_profile,
|
||||
model.ObjectType_note,
|
||||
model.ObjectType_collection,
|
||||
}, model.ObjectTypeLayout(layout)) // nolint:gosec
|
||||
}
|
||||
|
||||
func getLayoutStateFromMessages(msgs []simple.EventMessage) layoutState {
|
||||
ls := layoutState{}
|
||||
for _, ev := range msgs {
|
||||
if amend := ev.Msg.GetObjectDetailsAmend(); amend != nil {
|
||||
for _, detail := range amend.Details {
|
||||
switch detail.Key {
|
||||
case bundle.RelationKeyRecommendedLayout.String():
|
||||
ls.layout = int64(detail.Value.GetNumberValue())
|
||||
ls.isLayoutSet = true
|
||||
case bundle.RelationKeyRecommendedFeaturedRelations.String():
|
||||
ls.featuredRelations = pbtypes.GetStringListValue(detail.Value)
|
||||
ls.isFeaturedRelationsSet = true
|
||||
case bundle.RelationKeyLayoutAlign.String():
|
||||
ls.layoutAlign = int64(detail.Value.GetNumberValue())
|
||||
ls.isLayoutAlignSet = true
|
||||
}
|
||||
}
|
||||
if ls.isAllSet() {
|
||||
return ls
|
||||
}
|
||||
}
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
func getLayoutStateFromParent(ps *state.State) layoutState {
|
||||
ls := layoutState{}
|
||||
if ps == nil {
|
||||
return ls
|
||||
}
|
||||
|
||||
if layout, ok := ps.Details().TryInt64(bundle.RelationKeyRecommendedLayout); ok {
|
||||
ls.layout = layout
|
||||
ls.isLayoutSet = true
|
||||
}
|
||||
|
||||
if layoutAlign, ok := ps.Details().TryInt64(bundle.RelationKeyLayoutAlign); ok {
|
||||
ls.layoutAlign = layoutAlign
|
||||
ls.isLayoutAlignSet = true
|
||||
}
|
||||
|
||||
featuredRelations, ok := ps.Details().TryStringList(bundle.RelationKeyRecommendedFeaturedRelations)
|
||||
// featuredRelations can present in objects as empty slice or containing only description
|
||||
if ok && len(featuredRelations) != 0 && !slices.Equal(featuredRelations, []string{bundle.RelationKeyDescription.String()}) {
|
||||
ls.featuredRelations = featuredRelations
|
||||
ls.isFeaturedRelationsSet = true
|
||||
}
|
||||
return ls
|
||||
}
|
||||
|
||||
func (ot *ObjectType) queryObjectsAndTemplates() ([]database.Record, error) {
|
||||
records, err := ot.spaceIndex.Query(database.Query{Filters: []database.FilterRequest{
|
||||
{
|
||||
RelationKey: bundle.RelationKeyType,
|
||||
Condition: model.BlockContentDataviewFilter_Equal,
|
||||
Value: domain.String(ot.Id()),
|
||||
},
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get objects of single type: %w", err)
|
||||
}
|
||||
|
||||
templates, err := ot.spaceIndex.Query(database.Query{Filters: []database.FilterRequest{
|
||||
{
|
||||
RelationKey: bundle.RelationKeyTargetObjectType,
|
||||
Condition: model.BlockContentDataviewFilter_Equal,
|
||||
Value: domain.String(ot.Id()),
|
||||
},
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get templates with this target type: %w", err)
|
||||
}
|
||||
|
||||
return append(records, templates...), nil
|
||||
}
|
||||
|
||||
type layoutRelationsChanges struct {
|
||||
relationsToRemove []domain.RelationKey
|
||||
isLayoutFound bool
|
||||
isFeaturedRelationsChanged bool
|
||||
newFeaturedRelations []string
|
||||
}
|
||||
|
||||
func collectRelationsChanges(details *domain.Details, newLayout, oldLayout layoutState, deriver relationIdDeriver) (changes layoutRelationsChanges) {
|
||||
changes.relationsToRemove = make([]domain.RelationKey, 0, 2)
|
||||
if newLayout.isLayoutSet {
|
||||
layout, found := details.TryInt64(bundle.RelationKeyLayout)
|
||||
if found {
|
||||
changes.isLayoutFound = true
|
||||
if layout == newLayout.layout || oldLayout.isLayoutSet && layout == oldLayout.layout {
|
||||
changes.relationsToRemove = append(changes.relationsToRemove, bundle.RelationKeyLayout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if newLayout.isLayoutAlignSet {
|
||||
layoutAlign, found := details.TryInt64(bundle.RelationKeyLayoutAlign)
|
||||
if found && (layoutAlign == newLayout.layoutAlign || oldLayout.isLayoutAlignSet && layoutAlign == oldLayout.layoutAlign) {
|
||||
changes.relationsToRemove = append(changes.relationsToRemove, bundle.RelationKeyLayoutAlign)
|
||||
}
|
||||
}
|
||||
|
||||
if newLayout.isFeaturedRelationsSet {
|
||||
featuredRelations, found := details.TryStringList(bundle.RelationKeyFeaturedRelations)
|
||||
if found && isFeaturedRelationsCorrespondToType(featuredRelations, newLayout, oldLayout, deriver) {
|
||||
changes.isFeaturedRelationsChanged = true
|
||||
changes.newFeaturedRelations = []string{}
|
||||
if slices.Contains(featuredRelations, bundle.RelationKeyDescription.String()) {
|
||||
changes.newFeaturedRelations = append(changes.newFeaturedRelations, bundle.RelationKeyDescription.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func isFeaturedRelationsCorrespondToType(fr []string, newLayout, oldLayout layoutState, deriver relationIdDeriver) bool {
|
||||
featuredRelationIds := make([]string, 0, len(fr))
|
||||
for _, key := range fr {
|
||||
id, err := deriver.deriveId(domain.RelationKey(key))
|
||||
if err != nil {
|
||||
log.Errorf("failed to derive relation key %s", key)
|
||||
return false // let's fallback to true, so featuredRelations won't be changed
|
||||
}
|
||||
featuredRelationIds = append(featuredRelationIds, id)
|
||||
}
|
||||
|
||||
if newLayout.isFeaturedRelationsSet && slices.Equal(featuredRelationIds, newLayout.featuredRelations) {
|
||||
return true
|
||||
}
|
||||
|
||||
return oldLayout.isFeaturedRelationsSet && slices.Equal(featuredRelationIds, oldLayout.featuredRelations)
|
||||
}
|
401
core/block/editor/objecttype_test.go
Normal file
401
core/block/editor/objecttype_test.go
Normal file
|
@ -0,0 +1,401 @@
|
|||
package editor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/any-sync/app/ocache"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock/smarttest"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
||||
const (
|
||||
spaceId = "spc"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
sb *smarttest.SmartTest
|
||||
store *objectstore.StoreFixture
|
||||
space *smartblock.MockSpace
|
||||
*ObjectType
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T, id string) *fixture {
|
||||
sb := smarttest.New(id)
|
||||
store := objectstore.NewStoreFixture(t)
|
||||
spc := smartblock.NewMockSpace(t)
|
||||
sb.SetSpace(spc)
|
||||
page := &ObjectType{
|
||||
SmartBlock: sb,
|
||||
spaceIndex: store.SpaceIndex(spaceId),
|
||||
}
|
||||
|
||||
return &fixture{
|
||||
sb: sb,
|
||||
store: store,
|
||||
space: spc,
|
||||
ObjectType: page,
|
||||
}
|
||||
}
|
||||
|
||||
func TestObjectType_syncLayoutForObjectsAndTemplates(t *testing.T) {
|
||||
typeId := bundle.TypeKeyTask.URL()
|
||||
t.Run("recommendedLayout is updated", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(t, typeId)
|
||||
fx.sb.SetType(coresb.SmartBlockTypeObjectType)
|
||||
|
||||
fx.store.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj1"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
// layout detail should be deleted from obj1, because its value equals old recommendedLayout value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj2"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_todo)),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_todo)),
|
||||
// layout detail should be deleted from obj2, because its value equals new recommendedLayout value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj3"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_profile)),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_profile)),
|
||||
// obj3 should not be modified, because old layout does not correspond to old and new recommendedLayout values
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj4"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
// obj4 does not have layout detail set, so it has nothing to delete
|
||||
// StateAppend must be called for this object because resolvedLayout must be reinjected
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj5"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_note)),
|
||||
// obj5 does not have layout detail set, so it has nothing to delete
|
||||
// StateAppend must be called for this object because resolvedLayout must be reinjected
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj6"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_todo)),
|
||||
// obj6 does not have layout detail set, so it has nothing to delete
|
||||
// obj6 will not be modified, because it already has correct resolvedLauout value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("tmpl"),
|
||||
bundle.RelationKeyType: domain.String(bundle.TypeKeyTemplate.URL()),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
bundle.RelationKeyTargetObjectType: domain.String(typeId),
|
||||
// layout detail should be deleted from template, because its value equals old recommendedLayout value
|
||||
},
|
||||
})
|
||||
|
||||
obj1 := smarttest.New("obj1")
|
||||
require.NoError(t, obj1.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyLayout, Value: domain.Int64(int64(model.ObjectType_basic)),
|
||||
}}, false))
|
||||
obj2 := smarttest.New("obj2")
|
||||
require.NoError(t, obj2.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyLayout, Value: domain.Int64(int64(model.ObjectType_todo)),
|
||||
}}, false))
|
||||
obj4 := smarttest.New("obj4")
|
||||
tmpl := smarttest.New("tmpl")
|
||||
require.NoError(t, tmpl.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyLayout, Value: domain.Int64(int64(model.ObjectType_basic)),
|
||||
}}, false))
|
||||
|
||||
fx.space.EXPECT().DoLockedIfNotExists(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func() error) error {
|
||||
switch id {
|
||||
case "obj4":
|
||||
return ocache.ErrExists
|
||||
case "obj5":
|
||||
return f()
|
||||
default:
|
||||
panic("DoLockedIfNotExists: invalid object id")
|
||||
}
|
||||
})
|
||||
|
||||
fx.space.EXPECT().Do(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func(smartblock.SmartBlock) error) error {
|
||||
switch id {
|
||||
case "obj1":
|
||||
assert.NoError(t, f(obj1))
|
||||
case "obj2":
|
||||
assert.NoError(t, f(obj2))
|
||||
case "obj4":
|
||||
assert.NoError(t, f(obj4))
|
||||
case "tmpl":
|
||||
assert.NoError(t, f(tmpl))
|
||||
default:
|
||||
panic("Do: invalid object id")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// when
|
||||
err := fx.syncLayoutForObjectsAndTemplates(makeApplyInfo(typeId,
|
||||
// recommendedLayout is changed: basic -> todo
|
||||
layoutState{isLayoutSet: true, layout: int64(model.ObjectType_basic)},
|
||||
layoutState{isLayoutSet: true, layout: int64(model.ObjectType_todo)},
|
||||
))
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.False(t, obj1.Details().Has(bundle.RelationKeyLayout))
|
||||
assert.False(t, obj2.Details().Has(bundle.RelationKeyLayout))
|
||||
assert.False(t, tmpl.Details().Has(bundle.RelationKeyLayout))
|
||||
|
||||
assert.True(t, obj4.Results.IsStateAppendCalled)
|
||||
details, err := fx.spaceIndex.GetDetails("obj5")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(model.ObjectType_todo), details.GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
})
|
||||
|
||||
t.Run("layoutAlign is updated", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(t, typeId)
|
||||
fx.sb.SetType(coresb.SmartBlockTypeObjectType)
|
||||
|
||||
fx.store.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj1"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyLayoutAlign: domain.Int64(int64(model.Block_AlignLeft)),
|
||||
// layoutAlign detail should be deleted from obj1, because its value equals old type layoutAlign value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj2"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyLayoutAlign: domain.Int64(int64(model.Block_AlignRight)),
|
||||
// layoutAlign detail should be deleted from obj2, because its value equals new type layoutAlign value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj3"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyLayoutAlign: domain.Int64(int64(model.Block_AlignCenter)),
|
||||
// obj3 should not be modified, because layoutAlign does not correspond to old and new type layoutAlign values
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj4"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
// obj4 does not have layoutAlign detail set, so it has nothing to delete
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("tmpl"),
|
||||
bundle.RelationKeyType: domain.String(bundle.TypeKeyTemplate.URL()),
|
||||
bundle.RelationKeyLayoutAlign: domain.Int64(int64(model.Block_AlignRight)),
|
||||
bundle.RelationKeyTargetObjectType: domain.String(typeId),
|
||||
// layoutAlign detail should be deleted from template, because its value equals new type layoutAlign value
|
||||
},
|
||||
})
|
||||
|
||||
obj1 := smarttest.New("obj1")
|
||||
require.NoError(t, obj1.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyLayoutAlign, Value: domain.Int64(int64(model.ObjectType_basic)),
|
||||
}}, false))
|
||||
obj2 := smarttest.New("obj2")
|
||||
require.NoError(t, obj2.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyLayoutAlign, Value: domain.Int64(int64(model.ObjectType_todo)),
|
||||
}}, false))
|
||||
tmpl := smarttest.New("tmpl")
|
||||
require.NoError(t, tmpl.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyLayoutAlign, Value: domain.Int64(int64(model.ObjectType_basic)),
|
||||
}}, false))
|
||||
|
||||
fx.space.EXPECT().Do(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func(smartblock.SmartBlock) error) error {
|
||||
switch id {
|
||||
case "obj1":
|
||||
assert.NoError(t, f(obj1))
|
||||
case "obj2":
|
||||
assert.NoError(t, f(obj2))
|
||||
case "tmpl":
|
||||
assert.NoError(t, f(tmpl))
|
||||
default:
|
||||
panic("Do: invalid object id")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// when
|
||||
err := fx.syncLayoutForObjectsAndTemplates(makeApplyInfo(typeId,
|
||||
// recommendedLayout is changed: basic -> todo
|
||||
layoutState{isLayoutAlignSet: true, layoutAlign: int64(model.Block_AlignLeft)},
|
||||
layoutState{isLayoutAlignSet: true, layoutAlign: int64(model.Block_AlignRight)},
|
||||
))
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.False(t, obj1.Details().Has(bundle.RelationKeyLayoutAlign))
|
||||
assert.False(t, obj2.Details().Has(bundle.RelationKeyLayoutAlign))
|
||||
assert.False(t, tmpl.Details().Has(bundle.RelationKeyLayoutAlign))
|
||||
})
|
||||
|
||||
t.Run("recommendedFeaturedRelations is updated", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(t, typeId)
|
||||
fx.sb.SetType(coresb.SmartBlockTypeObjectType)
|
||||
|
||||
fx.store.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj1"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyFeaturedRelations: domain.StringList([]string{
|
||||
bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(),
|
||||
}),
|
||||
// featuredRelations detail should be cleared in obj1, because its value corresponds to old recommendedFeaturedRelations value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj2"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyFeaturedRelations: domain.StringList([]string{
|
||||
bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(), bundle.RelationKeyCreator.String(),
|
||||
}),
|
||||
// featuredRelations detail should be cleared in obj1, because its value corresponds to new recommendedFeaturedRelations value
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj3"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyFeaturedRelations: domain.StringList([]string{
|
||||
bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(), bundle.RelationKeyBacklinks.String(),
|
||||
}),
|
||||
// obj3 should not be modified, because featuredRelations does not correspond to old and new recommendedFeaturedRelations values
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj4"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyFeaturedRelations: domain.StringList([]string{
|
||||
bundle.RelationKeyDescription.String(),
|
||||
}),
|
||||
// featuredRelations of obj4 contains only description, so obj4 has nothing to delete
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("tmpl"),
|
||||
bundle.RelationKeyType: domain.String(bundle.TypeKeyTemplate.URL()),
|
||||
bundle.RelationKeyFeaturedRelations: domain.StringList([]string{}),
|
||||
bundle.RelationKeyTargetObjectType: domain.String(typeId),
|
||||
// featuredRelations of template is empty, so it has nothing to delete
|
||||
},
|
||||
})
|
||||
|
||||
obj1 := smarttest.New("obj1")
|
||||
require.NoError(t, obj1.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyFeaturedRelations, Value: domain.StringList([]string{
|
||||
bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(),
|
||||
}),
|
||||
}}, false))
|
||||
obj2 := smarttest.New("obj2")
|
||||
require.NoError(t, obj2.SetDetails(nil, []domain.Detail{{
|
||||
Key: bundle.RelationKeyFeaturedRelations, Value: domain.StringList([]string{
|
||||
bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(), bundle.RelationKeyCreator.String(),
|
||||
}),
|
||||
}}, false))
|
||||
|
||||
fx.space.EXPECT().Do(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func(smartblock.SmartBlock) error) error {
|
||||
switch id {
|
||||
case "obj1":
|
||||
assert.NoError(t, f(obj1))
|
||||
case "obj2":
|
||||
assert.NoError(t, f(obj2))
|
||||
default:
|
||||
panic("Do: invalid object id")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
fx.space.EXPECT().DeriveObjectID(mock.Anything, mock.Anything).RunAndReturn(func(_ context.Context, key domain.UniqueKey) (string, error) {
|
||||
return key.Marshal(), nil
|
||||
})
|
||||
|
||||
// when
|
||||
err := fx.syncLayoutForObjectsAndTemplates(makeApplyInfo(typeId,
|
||||
// recommendedLayout is changed: basic -> todo
|
||||
layoutState{isFeaturedRelationsSet: true, featuredRelations: []string{
|
||||
bundle.RelationKeyType.URL(), bundle.RelationKeyTag.URL(),
|
||||
}},
|
||||
layoutState{isFeaturedRelationsSet: true, featuredRelations: []string{
|
||||
bundle.RelationKeyType.URL(), bundle.RelationKeyTag.URL(), bundle.RelationKeyCreator.URL(),
|
||||
}},
|
||||
))
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
||||
require.True(t, obj1.Details().Has(bundle.RelationKeyFeaturedRelations))
|
||||
assert.Empty(t, obj1.Details().GetStringList(bundle.RelationKeyFeaturedRelations))
|
||||
require.True(t, obj2.Details().Has(bundle.RelationKeyFeaturedRelations))
|
||||
assert.Empty(t, obj2.Details().GetStringList(bundle.RelationKeyFeaturedRelations))
|
||||
})
|
||||
}
|
||||
|
||||
func makeApplyInfo(typeId string, oldLS, newLS layoutState) smartblock.ApplyInfo {
|
||||
events := make([]simple.EventMessage, 0, 3)
|
||||
if newLS.isLayoutSet {
|
||||
events = append(events, makeObjectDetailsAmendMsg(domain.Detail{
|
||||
Key: bundle.RelationKeyRecommendedLayout,
|
||||
Value: domain.Int64(newLS.layout),
|
||||
}))
|
||||
}
|
||||
|
||||
if newLS.isLayoutAlignSet {
|
||||
events = append(events, makeObjectDetailsAmendMsg(domain.Detail{
|
||||
Key: bundle.RelationKeyLayoutAlign,
|
||||
Value: domain.Int64(newLS.layoutAlign),
|
||||
}))
|
||||
}
|
||||
|
||||
if newLS.isFeaturedRelationsSet {
|
||||
events = append(events, makeObjectDetailsAmendMsg(domain.Detail{
|
||||
Key: bundle.RelationKeyRecommendedFeaturedRelations,
|
||||
Value: domain.StringList(newLS.featuredRelations),
|
||||
}))
|
||||
}
|
||||
|
||||
ps := state.NewDoc(typeId, nil).NewState().SetDetails(domain.NewDetails())
|
||||
if oldLS.isLayoutSet {
|
||||
ps.SetDetail(bundle.RelationKeyRecommendedLayout, domain.Int64(oldLS.layout))
|
||||
}
|
||||
if oldLS.isLayoutAlignSet {
|
||||
ps.SetDetail(bundle.RelationKeyLayoutAlign, domain.Int64(oldLS.layoutAlign))
|
||||
}
|
||||
if oldLS.isFeaturedRelationsSet {
|
||||
ps.SetDetail(bundle.RelationKeyRecommendedFeaturedRelations, domain.StringList(oldLS.featuredRelations))
|
||||
}
|
||||
|
||||
return smartblock.ApplyInfo{
|
||||
Events: events,
|
||||
ParentState: ps,
|
||||
}
|
||||
}
|
||||
|
||||
func makeObjectDetailsAmendMsg(detail domain.Detail) simple.EventMessage {
|
||||
return simple.EventMessage{
|
||||
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfObjectDetailsAmend{ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
|
||||
Details: []*pb.EventObjectDetailsAmendKeyValue{{
|
||||
Key: detail.Key.String(),
|
||||
Value: detail.Value.ToProto(),
|
||||
}},
|
||||
}}},
|
||||
}
|
||||
}
|
|
@ -33,7 +33,6 @@ var pageRequiredRelations = []domain.RelationKey{
|
|||
bundle.RelationKeyLinks,
|
||||
bundle.RelationKeyBacklinks,
|
||||
bundle.RelationKeyMentions,
|
||||
bundle.RelationKeyLayoutAlign,
|
||||
}
|
||||
|
||||
var typeAndRelationRequiredRelations = []domain.RelationKey{
|
||||
|
@ -45,17 +44,6 @@ var typeAndRelationRequiredRelations = []domain.RelationKey{
|
|||
bundle.RelationKeyIsHidden,
|
||||
}
|
||||
|
||||
var typeRequiredRelations = append(typeAndRelationRequiredRelations,
|
||||
bundle.RelationKeyRecommendedRelations,
|
||||
bundle.RelationKeyRecommendedFeaturedRelations,
|
||||
bundle.RelationKeyRecommendedHiddenRelations,
|
||||
bundle.RelationKeyRecommendedFileRelations,
|
||||
bundle.RelationKeyRecommendedLayout,
|
||||
bundle.RelationKeySmartblockTypes,
|
||||
bundle.RelationKeyIconOption,
|
||||
bundle.RelationKeyIconName,
|
||||
)
|
||||
|
||||
var relationRequiredRelations = append(typeAndRelationRequiredRelations,
|
||||
bundle.RelationKeyRelationFormat,
|
||||
bundle.RelationKeyRelationFormatObjectTypes,
|
||||
|
@ -214,11 +202,8 @@ func (p *Page) CreationStateMigration(ctx *smartblock.InitContext) migration.Mig
|
|||
templates := []template.StateTransformer{
|
||||
template.WithEmpty,
|
||||
template.WithObjectTypes(ctx.State.ObjectTypeKeys()),
|
||||
template.WithResolvedLayout(layout),
|
||||
template.WithDefaultFeaturedRelations,
|
||||
template.WithFeaturedRelations,
|
||||
template.WithFeaturedRelationsBlock,
|
||||
template.WithLinkFieldsMigration,
|
||||
template.WithCreatorRemovedFromFeaturedRelations,
|
||||
}
|
||||
|
||||
switch layout {
|
||||
|
@ -237,20 +222,11 @@ func (p *Page) CreationStateMigration(ctx *smartblock.InitContext) migration.Mig
|
|||
templates = append(templates,
|
||||
template.WithTitle,
|
||||
template.WithDescription,
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyType),
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyBacklinks),
|
||||
template.WithBookmarkBlocks,
|
||||
)
|
||||
case model.ObjectType_relation:
|
||||
templates = append(templates,
|
||||
template.WithTitle,
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyType),
|
||||
template.WithLayout(layout),
|
||||
)
|
||||
case model.ObjectType_objectType:
|
||||
templates = append(templates,
|
||||
template.WithTitle,
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyType),
|
||||
template.WithLayout(layout),
|
||||
)
|
||||
case model.ObjectType_chat:
|
||||
|
@ -287,7 +263,7 @@ func (p *Page) StateMigrations() migration.Migrations {
|
|||
return migration.MakeMigrations([]migration.Migration{
|
||||
{
|
||||
Version: 2,
|
||||
Proc: template.WithAddedFeaturedRelation(bundle.RelationKeyBacklinks),
|
||||
Proc: func(s *state.State) {},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -62,11 +62,8 @@ func (p *participant) Init(ctx *smartblock.InitContext) (err error) {
|
|||
template.WithEmpty,
|
||||
template.WithTitle,
|
||||
template.WithDescription,
|
||||
template.WithFeaturedRelations,
|
||||
template.WithFeaturedRelationsBlock,
|
||||
template.WithLayout(model.ObjectType_participant),
|
||||
template.WithResolvedLayout(model.ObjectType_participant),
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyType),
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyBacklinks),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -82,7 +82,6 @@ func (p *Profile) CreationStateMigration(ctx *smartblock.InitContext) migration.
|
|||
template.InitTemplate(st,
|
||||
template.WithObjectTypes([]domain.TypeKey{bundle.TypeKeyProfile}),
|
||||
template.WithLayout(model.ObjectType_profile),
|
||||
template.WithResolvedLayout(model.ObjectType_profile),
|
||||
template.WithDetail(bundle.RelationKeyLayoutAlign, domain.Int64(model.Block_AlignCenter)),
|
||||
migrationSetHidden,
|
||||
)
|
||||
|
|
|
@ -236,6 +236,12 @@ func (sb *smartBlock) injectResolvedLayout(s *state.State) {
|
|||
}
|
||||
|
||||
typeObjectId := s.LocalDetails().GetString(bundle.RelationKeyType)
|
||||
|
||||
if s.ObjectTypeKey() == bundle.TypeKeyTemplate {
|
||||
// resolvedLayout for templates should be derived from target type
|
||||
typeObjectId = s.Details().GetString(bundle.RelationKeyTargetObjectType)
|
||||
}
|
||||
|
||||
if typeObjectId == "" {
|
||||
if currentValue := s.LocalDetails().Get(bundle.RelationKeyResolvedLayout); currentValue.Ok() {
|
||||
return
|
||||
|
@ -245,16 +251,7 @@ func (sb *smartBlock) injectResolvedLayout(s *state.State) {
|
|||
return
|
||||
}
|
||||
|
||||
var parentLayoutValue domain.Value
|
||||
parent := s.ParentState()
|
||||
if parent != nil {
|
||||
parentLayoutValue = parent.Details().Get(bundle.RelationKeyLayout)
|
||||
}
|
||||
|
||||
if currentValue := s.LocalDetails().Get(bundle.RelationKeyResolvedLayout); currentValue.Ok() && !parentLayoutValue.Ok() {
|
||||
// we can leave current value as is, if layout is not being unset right now
|
||||
return
|
||||
}
|
||||
currentValue := s.LocalDetails().Get(bundle.RelationKeyResolvedLayout)
|
||||
|
||||
typeDetails, found := sb.lastDepDetails[typeObjectId]
|
||||
if found {
|
||||
|
@ -263,6 +260,9 @@ func (sb *smartBlock) injectResolvedLayout(s *state.State) {
|
|||
records, err := sb.objectStore.SpaceIndex(sb.SpaceID()).QueryByIds([]string{typeObjectId})
|
||||
if err != nil || len(records) != 1 {
|
||||
log.Errorf("failed to query object %s: %v", typeObjectId, err)
|
||||
if currentValue.Ok() {
|
||||
return
|
||||
}
|
||||
s.SetDetailAndBundledRelation(bundle.RelationKeyResolvedLayout, domain.Int64(int64(model.ObjectType_basic)))
|
||||
return
|
||||
}
|
||||
|
@ -270,6 +270,9 @@ func (sb *smartBlock) injectResolvedLayout(s *state.State) {
|
|||
}
|
||||
|
||||
if !rawValue.Ok() {
|
||||
if currentValue.Ok() {
|
||||
return
|
||||
}
|
||||
log.Errorf("failed to get recommended layout from details of type. Fallback to basic layout")
|
||||
s.SetDetailAndBundledRelation(bundle.RelationKeyResolvedLayout, domain.Int64(int64(model.ObjectType_basic)))
|
||||
return
|
||||
|
|
|
@ -6,15 +6,12 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/app/ocache"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
|
@ -303,7 +300,7 @@ func TestInjectResolvedLayout(t *testing.T) {
|
|||
// then
|
||||
assert.Equal(t, int64(model.ObjectType_todo), st.LocalDetails().GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
})
|
||||
t.Run("resolved layout is already injected", func(t *testing.T) {
|
||||
t.Run("failed to get type object id -> fallback to already sey resolvedLayout", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(id, t)
|
||||
|
||||
|
@ -316,7 +313,7 @@ func TestInjectResolvedLayout(t *testing.T) {
|
|||
// then
|
||||
assert.Equal(t, int64(model.ObjectType_set), st.LocalDetails().GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
})
|
||||
t.Run("failed to get type object id -> fallback to basic", func(t *testing.T) {
|
||||
t.Run("failed to get type object id and resolvedLayout is not set -> fallback to basic", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(id, t)
|
||||
|
||||
|
@ -334,6 +331,7 @@ func TestInjectResolvedLayout(t *testing.T) {
|
|||
|
||||
st := state.NewDoc("id", nil).NewState()
|
||||
st.SetLocalDetail(bundle.RelationKeyType, domain.String(bundle.TypeKeyTask.URL()))
|
||||
st.SetLocalDetail(bundle.RelationKeyResolvedLayout, domain.Int64(model.ObjectType_basic))
|
||||
|
||||
fx.lastDepDetails = map[string]*domain.Details{
|
||||
bundle.TypeKeyTask.URL(): domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
|
@ -353,6 +351,7 @@ func TestInjectResolvedLayout(t *testing.T) {
|
|||
|
||||
st := state.NewDoc("id", nil).NewState()
|
||||
st.SetLocalDetail(bundle.RelationKeyType, domain.String(bundle.TypeKeyProfile.URL()))
|
||||
st.SetLocalDetail(bundle.RelationKeyResolvedLayout, domain.Int64(model.ObjectType_basic))
|
||||
|
||||
fx.objectStore.AddObjects(t, testSpaceId, []objectstore.TestObject{{
|
||||
bundle.RelationKeyId: domain.String(bundle.TypeKeyProfile.URL()),
|
||||
|
@ -378,135 +377,28 @@ func TestInjectResolvedLayout(t *testing.T) {
|
|||
// then
|
||||
assert.Equal(t, int64(model.ObjectType_basic), st.LocalDetails().GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
})
|
||||
t.Run("layout is resolved from object store, because layout relation is deleted", func(t *testing.T) {
|
||||
t.Run("layout for template is resolved from target type", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(id, t)
|
||||
|
||||
st := state.NewDoc("id", nil).NewState()
|
||||
st.SetDetail(bundle.RelationKeyCoverId, domain.String("red"))
|
||||
st.SetLocalDetail(bundle.RelationKeyType, domain.String(bundle.TypeKeyProfile.URL()))
|
||||
st.SetLocalDetail(bundle.RelationKeyResolvedLayout, domain.Int64(model.ObjectType_todo))
|
||||
st.ParentState().SetDetail(bundle.RelationKeyLayout, domain.Int64(model.ObjectType_todo))
|
||||
st.SetDetail(bundle.RelationKeyTargetObjectType, domain.String(bundle.TypeKeyTask.URL()))
|
||||
st.SetLocalDetail(bundle.RelationKeyType, domain.String(bundle.TypeKeyTemplate.URL()))
|
||||
st.SetLocalDetail(bundle.RelationKeyResolvedLayout, domain.Int64(model.ObjectType_note))
|
||||
st.SetObjectTypeKey(bundle.TypeKeyTemplate)
|
||||
|
||||
fx.objectStore.AddObjects(t, testSpaceId, []objectstore.TestObject{{
|
||||
bundle.RelationKeyId: domain.String(bundle.TypeKeyProfile.URL()),
|
||||
bundle.RelationKeyId: domain.String(bundle.TypeKeyTemplate.URL()),
|
||||
bundle.RelationKeyRecommendedLayout: domain.Int64(model.ObjectType_profile),
|
||||
}, {
|
||||
bundle.RelationKeyId: domain.String(bundle.TypeKeyTask.URL()),
|
||||
bundle.RelationKeyRecommendedLayout: domain.Int64(model.ObjectType_todo),
|
||||
}})
|
||||
|
||||
// when
|
||||
fx.injectResolvedLayout(st)
|
||||
|
||||
// then
|
||||
assert.Equal(t, int64(model.ObjectType_profile), st.LocalDetails().GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
assert.Equal(t, int64(model.ObjectType_todo), st.LocalDetails().GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
})
|
||||
}
|
||||
|
||||
func TestChangeResolvedLayoutForObjects(t *testing.T) {
|
||||
typeId := "typeId"
|
||||
t.Run("change resolvedLayout, do not delete layout", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(typeId, t)
|
||||
fx.source.sbType = smartblock.SmartBlockTypeObjectType
|
||||
|
||||
fx.objectStore.AddObjects(t, testSpaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj1"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj2"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_todo)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj3"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_profile)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("tmpl"),
|
||||
bundle.RelationKeyType: domain.String(bundle.TypeKeyTemplate.URL()),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
bundle.RelationKeyTargetObjectType: domain.String(typeId),
|
||||
},
|
||||
})
|
||||
|
||||
fx.space.EXPECT().DoLockedIfNotExists(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func() error) error {
|
||||
if id == "obj1" || id == "tmpl" {
|
||||
return f()
|
||||
}
|
||||
return ocache.ErrExists
|
||||
})
|
||||
|
||||
fx.space.EXPECT().Do(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func(SmartBlock) error) error {
|
||||
assert.Equal(t, "obj3", id)
|
||||
return nil
|
||||
})
|
||||
|
||||
// when
|
||||
err := fx.changeResolvedLayoutForObjects(makeLayoutChanges(int64(model.ObjectType_todo)), false)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("change resolvedLayout, do not delete layout", func(t *testing.T) {
|
||||
// given
|
||||
fx := newFixture(typeId, t)
|
||||
fx.source.sbType = smartblock.SmartBlockTypeObjectType
|
||||
|
||||
fx.objectStore.AddObjects(t, testSpaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj1"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_basic)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj2"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_todo)),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_todo)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj3"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_profile)),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("obj4"),
|
||||
bundle.RelationKeyType: domain.String(typeId),
|
||||
bundle.RelationKeyResolvedLayout: domain.Int64(int64(model.ObjectType_note)),
|
||||
},
|
||||
})
|
||||
|
||||
fx.space.EXPECT().DoLockedIfNotExists(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func() error) error {
|
||||
assert.Equal(t, "obj4", id)
|
||||
return f()
|
||||
})
|
||||
|
||||
counter := 0
|
||||
fx.space.EXPECT().Do(mock.Anything, mock.Anything).RunAndReturn(func(id string, f func(SmartBlock) error) error {
|
||||
counter++
|
||||
return nil
|
||||
})
|
||||
|
||||
// when
|
||||
err := fx.changeResolvedLayoutForObjects(makeLayoutChanges(int64(model.ObjectType_todo)), true)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, counter)
|
||||
})
|
||||
}
|
||||
|
||||
func makeLayoutChanges(layout int64) []simple.EventMessage {
|
||||
return []simple.EventMessage{{
|
||||
Msg: &pb.EventMessage{Value: &pb.EventMessageValueOfObjectDetailsAmend{ObjectDetailsAmend: &pb.EventObjectDetailsAmend{
|
||||
Details: []*pb.EventObjectDetailsAmendKeyValue{{
|
||||
Key: bundle.RelationKeyRecommendedLayout.String(),
|
||||
Value: domain.Int64(layout).ToProto(),
|
||||
},
|
||||
}}}},
|
||||
}}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/event"
|
||||
"github.com/anyproto/anytype-heart/core/relationutils"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
|
@ -70,9 +69,10 @@ const (
|
|||
type Hook int
|
||||
|
||||
type ApplyInfo struct {
|
||||
State *state.State
|
||||
Events []simple.EventMessage
|
||||
Changes []*pb.ChangeContent
|
||||
State *state.State
|
||||
ParentState *state.State
|
||||
Events []simple.EventMessage
|
||||
Changes []*pb.ChangeContent
|
||||
}
|
||||
|
||||
type HookCallback func(info ApplyInfo) (err error)
|
||||
|
@ -628,7 +628,6 @@ func (sb *smartBlock) EnabledRelationAsDependentObjects() {
|
|||
}
|
||||
|
||||
func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
|
||||
startTime := time.Now()
|
||||
if sb.IsDeleted() {
|
||||
return domain.ErrObjectIsDeleted
|
||||
}
|
||||
|
@ -700,10 +699,9 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
|
|||
removeInternalFlags(s)
|
||||
}
|
||||
|
||||
beforeApplyStateTime := time.Now()
|
||||
|
||||
migrationVersionUpdated := true
|
||||
if parent := s.ParentState(); parent != nil {
|
||||
parent := s.ParentState()
|
||||
if parent != nil {
|
||||
migrationVersionUpdated = s.MigrationVersion() != parent.MigrationVersion()
|
||||
}
|
||||
|
||||
|
@ -712,15 +710,10 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = sb.changeResolvedLayoutForObjects(msgs, true); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// we may have layout changed, so we need to update restrictions
|
||||
sb.updateRestrictions()
|
||||
sb.setRestrictionsDetail(s)
|
||||
|
||||
afterApplyStateTime := time.Now()
|
||||
st := sb.Doc.(*state.State)
|
||||
|
||||
changes := st.GetChanges()
|
||||
|
@ -805,7 +798,6 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
|
|||
sb.runIndexer(st)
|
||||
}
|
||||
|
||||
afterPushChangeTime := time.Now()
|
||||
if sendEvent {
|
||||
events := msgsToEvents(msgs)
|
||||
if ctx := s.Context(); ctx != nil {
|
||||
|
@ -821,22 +813,16 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) {
|
|||
if hasDepIds(sb.GetRelationLinks(), &act) {
|
||||
sb.CheckSubscriptions()
|
||||
}
|
||||
afterReportChangeTime := time.Now()
|
||||
if hooks {
|
||||
if e := sb.execHooks(HookAfterApply, ApplyInfo{State: sb.Doc.(*state.State), Events: msgs, Changes: changes}); e != nil {
|
||||
if e := sb.execHooks(HookAfterApply, ApplyInfo{
|
||||
State: sb.Doc.(*state.State),
|
||||
ParentState: parent,
|
||||
Events: msgs,
|
||||
Changes: changes,
|
||||
}); e != nil {
|
||||
log.With("objectID", sb.Id()).Warnf("after apply execHooks error: %v", e)
|
||||
}
|
||||
}
|
||||
afterApplyHookTime := time.Now()
|
||||
|
||||
metrics.Service.Send(&metrics.StateApply{
|
||||
BeforeApplyMs: beforeApplyStateTime.Sub(startTime).Milliseconds(),
|
||||
StateApplyMs: afterApplyStateTime.Sub(beforeApplyStateTime).Milliseconds(),
|
||||
PushChangeMs: afterPushChangeTime.Sub(afterApplyStateTime).Milliseconds(),
|
||||
ReportChangeMs: afterReportChangeTime.Sub(afterPushChangeTime).Milliseconds(),
|
||||
ApplyHookMs: afterApplyHookTime.Sub(afterReportChangeTime).Milliseconds(),
|
||||
ObjectId: sb.Id(),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -962,10 +948,6 @@ func (sb *smartBlock) StateAppend(f func(d state.Doc) (s *state.State, changes [
|
|||
}
|
||||
log.Infof("changes: stateAppend: %d events", len(msgs))
|
||||
|
||||
if err = sb.changeResolvedLayoutForObjects(msgs, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(msgs) > 0 {
|
||||
sb.sendEvent(&pb.Event{
|
||||
Messages: msgsToEvents(msgs),
|
||||
|
@ -977,7 +959,14 @@ func (sb *smartBlock) StateAppend(f func(d state.Doc) (s *state.State, changes [
|
|||
sb.CheckSubscriptions()
|
||||
}
|
||||
sb.runIndexer(s)
|
||||
sb.execHooks(HookAfterApply, ApplyInfo{State: s, Events: msgs, Changes: changes})
|
||||
if err = sb.execHooks(HookAfterApply, ApplyInfo{
|
||||
State: s,
|
||||
ParentState: s.ParentState(),
|
||||
Events: msgs,
|
||||
Changes: changes,
|
||||
}); err != nil {
|
||||
log.Errorf("failed to execute smartblock hooks after apply on StateAppend: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -367,7 +367,8 @@ func (st *SmartTest) StateRebuild(d state.Doc) (err error) {
|
|||
}
|
||||
|
||||
func (st *SmartTest) StateAppend(func(d state.Doc) (s *state.State, changes []*pb.ChangeContent, err error)) error {
|
||||
panic("not implemented")
|
||||
st.Results.IsStateAppendCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *SmartTest) AddBlock(b simple.Block) *SmartTest {
|
||||
|
@ -423,6 +424,7 @@ func (st *SmartTest) Update(ctx session.Context, apply func(b simple.Block) erro
|
|||
}
|
||||
|
||||
type Results struct {
|
||||
Events [][]simple.EventMessage
|
||||
Applies [][]*model.Block
|
||||
Events [][]simple.EventMessage
|
||||
Applies [][]*model.Block
|
||||
IsStateAppendCalled bool
|
||||
}
|
||||
|
|
|
@ -116,7 +116,6 @@ func (s *SpaceView) initTemplate(st *state.State) {
|
|||
template.InitTemplate(st,
|
||||
template.WithObjectTypes([]domain.TypeKey{bundle.TypeKeySpaceView}),
|
||||
template.WithLayout(model.ObjectType_spaceView),
|
||||
template.WithResolvedLayout(model.ObjectType_spaceView),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
|
@ -20,6 +21,7 @@ var (
|
|||
|
||||
func (s *State) Normalize(withLayouts bool) (err error) {
|
||||
s.removeDuplicates()
|
||||
s.normalizeDetails()
|
||||
return s.normalize(withLayouts)
|
||||
}
|
||||
|
||||
|
@ -392,3 +394,32 @@ func CleanupLayouts(s *State) (removedCount int) {
|
|||
cleanup(s.RootId())
|
||||
return
|
||||
}
|
||||
|
||||
func (s *State) normalizeDetails() {
|
||||
if s.ObjectTypeKey() == bundle.TypeKeyObjectType {
|
||||
s.normalizeRecommendedRelations()
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeRecommendedRelations normalizes recommended relations of Type on state build level, because
|
||||
// these lists mustn't contain similar values, but could be updated by multiple clients independently
|
||||
func (s *State) normalizeRecommendedRelations() {
|
||||
details := s.details
|
||||
if details == nil && s.parent != nil {
|
||||
details = s.parent.details
|
||||
}
|
||||
if details == nil {
|
||||
return
|
||||
}
|
||||
|
||||
recRelations := details.GetStringList(bundle.RelationKeyRecommendedRelations)
|
||||
recFeatRelations := details.GetStringList(bundle.RelationKeyRecommendedFeaturedRelations)
|
||||
recHiddenRelations := details.GetStringList(bundle.RelationKeyRecommendedHiddenRelations)
|
||||
|
||||
recHiddenRelations = slice.RemoveN(recHiddenRelations, recFeatRelations...)
|
||||
recHiddenRelations = slice.RemoveN(recHiddenRelations, recRelations...)
|
||||
recRelations = slice.RemoveN(recRelations, recFeatRelations...)
|
||||
|
||||
details.SetStringList(bundle.RelationKeyRecommendedRelations, recRelations)
|
||||
details.SetStringList(bundle.RelationKeyRecommendedHiddenRelations, recHiddenRelations)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
|
@ -547,3 +548,26 @@ func countStringsLength(value *types.Value) (n int) {
|
|||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func TestNormalizeRecommendedRelations(t *testing.T) {
|
||||
// given
|
||||
s := NewDoc("root", nil).NewState().SetDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
bundle.RelationKeyRecommendedRelations: domain.StringList([]string{"s1", "sh", "sf", "sfh"}), // s stands for sidebar
|
||||
bundle.RelationKeyRecommendedFeaturedRelations: domain.StringList([]string{"f1", "f2", "sfh", "fh", "sf"}),
|
||||
bundle.RelationKeyRecommendedHiddenRelations: domain.StringList([]string{"sfh", "sh", "fh", "h1", "h2", "h3"}),
|
||||
}))
|
||||
child := s.NewState()
|
||||
|
||||
// when
|
||||
s.normalizeRecommendedRelations()
|
||||
child.normalizeRecommendedRelations()
|
||||
|
||||
// then
|
||||
assert.Equal(t, []string{"s1", "sh"}, s.Details().GetStringList(bundle.RelationKeyRecommendedRelations))
|
||||
assert.Equal(t, []string{"f1", "f2", "sfh", "fh", "sf"}, s.Details().GetStringList(bundle.RelationKeyRecommendedFeaturedRelations))
|
||||
assert.Equal(t, []string{"h1", "h2", "h3"}, s.Details().GetStringList(bundle.RelationKeyRecommendedHiddenRelations))
|
||||
|
||||
assert.Equal(t, []string{"s1", "sh"}, child.Details().GetStringList(bundle.RelationKeyRecommendedRelations))
|
||||
assert.Equal(t, []string{"f1", "f2", "sfh", "fh", "sf"}, child.Details().GetStringList(bundle.RelationKeyRecommendedFeaturedRelations))
|
||||
assert.Equal(t, []string{"h1", "h2", "h3"}, child.Details().GetStringList(bundle.RelationKeyRecommendedHiddenRelations))
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/event"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/spaceindex"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
|
@ -82,7 +81,6 @@ func (t *textImpl) UpdateTextBlocks(ctx session.Context, ids []string, showEvent
|
|||
}
|
||||
|
||||
func (t *textImpl) Split(ctx session.Context, req pb.RpcBlockSplitRequest) (newId string, err error) {
|
||||
startTime := time.Now()
|
||||
s := t.NewStateCtx(ctx)
|
||||
tb, err := getText(s, req.BlockId)
|
||||
if err != nil {
|
||||
|
@ -155,21 +153,13 @@ func (t *textImpl) Split(ctx session.Context, req pb.RpcBlockSplitRequest) (newI
|
|||
return
|
||||
}
|
||||
}
|
||||
algorithmMs := time.Now().Sub(startTime).Milliseconds()
|
||||
if err = t.Apply(s); err != nil {
|
||||
return
|
||||
}
|
||||
applyMs := time.Now().Sub(startTime).Milliseconds() - algorithmMs
|
||||
metrics.Service.Send(&metrics.BlockSplit{
|
||||
ObjectId: t.Id(),
|
||||
AlgorithmMs: algorithmMs,
|
||||
ApplyMs: applyMs,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (t *textImpl) Merge(ctx session.Context, firstId, secondId string) (err error) {
|
||||
startTime := time.Now()
|
||||
s := t.NewStateCtx(ctx)
|
||||
|
||||
// Don't merge blocks inside header block
|
||||
|
@ -196,16 +186,9 @@ func (t *textImpl) Merge(ctx session.Context, firstId, secondId string) (err err
|
|||
}
|
||||
s.Unlink(second.Model().Id)
|
||||
first.Model().ChildrenIds = append(first.Model().ChildrenIds, second.Model().ChildrenIds...)
|
||||
algorithmMs := time.Now().Sub(startTime).Milliseconds()
|
||||
if err = t.Apply(s); err != nil {
|
||||
return
|
||||
}
|
||||
applyMs := time.Now().Sub(startTime).Milliseconds() - algorithmMs
|
||||
metrics.Service.Send(&metrics.BlockMerge{
|
||||
ObjectId: t.Id(),
|
||||
AlgorithmMs: algorithmMs,
|
||||
ApplyMs: applyMs,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -100,20 +100,8 @@ var WithObjectTypes = func(otypes []domain.TypeKey) StateTransformer {
|
|||
}
|
||||
}
|
||||
|
||||
var WithResolvedLayout = func(layout model.ObjectTypeLayout) StateTransformer {
|
||||
return func(s *state.State) {
|
||||
if !s.LocalDetails().Has(bundle.RelationKeyResolvedLayout) {
|
||||
s.SetDetailAndBundledRelation(bundle.RelationKeyResolvedLayout, domain.Int64(layout))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var WithLayout = func(layout model.ObjectTypeLayout) StateTransformer {
|
||||
return func(s *state.State) {
|
||||
if !s.Details().Has(bundle.RelationKeyLayout) {
|
||||
s.SetDetailAndBundledRelation(bundle.RelationKeyLayout, domain.Int64(layout))
|
||||
}
|
||||
}
|
||||
return WithDetail(bundle.RelationKeyLayout, domain.Int64(layout))
|
||||
}
|
||||
|
||||
var WithDetailName = func(name string) StateTransformer {
|
||||
|
@ -228,38 +216,6 @@ var WithTitle = StateTransformer(func(s *state.State) {
|
|||
}
|
||||
})
|
||||
|
||||
// WithDefaultFeaturedRelations **MUST** be called before WithDescription
|
||||
var WithDefaultFeaturedRelations = func(s *state.State) {
|
||||
if !s.Details().Has(bundle.RelationKeyFeaturedRelations) {
|
||||
var fr = []string{bundle.RelationKeyType.String()}
|
||||
layout, _ := s.Layout()
|
||||
switch layout {
|
||||
case model.ObjectType_basic, model.ObjectType_note:
|
||||
fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeyBacklinks.String()}
|
||||
case model.ObjectType_set:
|
||||
fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeySetOf.String(), bundle.RelationKeyBacklinks.String()}
|
||||
case model.ObjectType_collection:
|
||||
fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeyBacklinks.String()}
|
||||
case model.ObjectType_file, model.ObjectType_image, model.ObjectType_audio, model.ObjectType_video, model.ObjectType_pdf:
|
||||
fr = []string{bundle.RelationKeyType.String(), bundle.RelationKeyTag.String(), bundle.RelationKeyBacklinks.String()}
|
||||
// Tag is not added to details of object explicitly as it is not system relation
|
||||
s.SetDetail(bundle.RelationKeyTag, domain.StringList([]string{}))
|
||||
}
|
||||
s.SetDetail(bundle.RelationKeyFeaturedRelations, domain.StringList(fr))
|
||||
}
|
||||
}
|
||||
|
||||
var WithAddedFeaturedRelation = func(key domain.RelationKey) StateTransformer {
|
||||
return func(s *state.State) {
|
||||
featRels := s.Details().GetStringList(bundle.RelationKeyFeaturedRelations)
|
||||
if slice.FindPos(featRels, key.String()) > -1 {
|
||||
return
|
||||
} else {
|
||||
s.SetDetail(bundle.RelationKeyFeaturedRelations, domain.StringList(append(featRels, key.String())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var WithRemovedFeaturedRelation = func(key domain.RelationKey) StateTransformer {
|
||||
return func(s *state.State) {
|
||||
var featRels = s.Details().GetStringList(bundle.RelationKeyFeaturedRelations)
|
||||
|
@ -270,18 +226,6 @@ var WithRemovedFeaturedRelation = func(key domain.RelationKey) StateTransformer
|
|||
}
|
||||
}
|
||||
|
||||
var WithCreatorRemovedFromFeaturedRelations = StateTransformer(func(s *state.State) {
|
||||
fr := s.Details().GetStringList(bundle.RelationKeyFeaturedRelations)
|
||||
|
||||
if slice.FindPos(fr, bundle.RelationKeyCreator.String()) != -1 {
|
||||
frc := make([]string, len(fr))
|
||||
copy(frc, fr)
|
||||
|
||||
frc = slice.RemoveMut(frc, bundle.RelationKeyCreator.String())
|
||||
s.SetDetail(bundle.RelationKeyFeaturedRelations, domain.StringList(frc))
|
||||
}
|
||||
})
|
||||
|
||||
var WithForcedDescription = func(s *state.State) {
|
||||
RequireHeader(s)
|
||||
|
||||
|
@ -331,7 +275,10 @@ var WithForcedDescription = func(s *state.State) {
|
|||
var WithDescription = func(s *state.State) {
|
||||
RequireHeader(s)
|
||||
|
||||
WithAddedFeaturedRelation(bundle.RelationKeyDescription)(s)
|
||||
featRels := s.Details().GetStringList(bundle.RelationKeyFeaturedRelations)
|
||||
if slice.FindPos(featRels, bundle.RelationKeyDescription.String()) == -1 {
|
||||
s.SetDetail(bundle.RelationKeyFeaturedRelations, domain.StringList(append(featRels, bundle.RelationKeyDescription.String())))
|
||||
}
|
||||
if !s.Exists(DescriptionBlockId) {
|
||||
WithForcedDescription(s)
|
||||
}
|
||||
|
@ -392,7 +339,7 @@ var WithNameToFirstBlock = StateTransformer(func(s *state.State) {
|
|||
}
|
||||
})
|
||||
|
||||
var WithFeaturedRelations = StateTransformer(func(s *state.State) {
|
||||
var WithFeaturedRelationsBlock = StateTransformer(func(s *state.State) {
|
||||
RequireHeader(s)
|
||||
|
||||
var align model.BlockAlign
|
||||
|
|
|
@ -55,7 +55,6 @@ func (w *WidgetObject) CreationStateMigration(ctx *smartblock.InitContext) migra
|
|||
template.WithEmpty,
|
||||
template.WithObjectTypes([]domain.TypeKey{bundle.TypeKeyDashboard}),
|
||||
template.WithLayout(model.ObjectType_dashboard),
|
||||
template.WithResolvedLayout(model.ObjectType_dashboard),
|
||||
template.WithDetail(bundle.RelationKeyIsHidden, domain.Bool(true)),
|
||||
)
|
||||
},
|
||||
|
|
|
@ -78,10 +78,9 @@ func (w *Workspaces) initTemplate(ctx *smartblock.InitContext) {
|
|||
template.InitTemplate(ctx.State,
|
||||
template.WithEmpty,
|
||||
template.WithTitle,
|
||||
template.WithFeaturedRelations,
|
||||
template.WithFeaturedRelationsBlock,
|
||||
template.WithDetail(bundle.RelationKeyIsHidden, domain.Bool(true)),
|
||||
template.WithLayout(model.ObjectType_space),
|
||||
template.WithResolvedLayout(model.ObjectType_space),
|
||||
template.WithForcedObjectTypes([]domain.TypeKey{bundle.TypeKeySpace}),
|
||||
template.WithForcedDetail(bundle.RelationKeyFeaturedRelations, domain.StringList([]string{bundle.RelationKeyType.String(), bundle.RelationKeyCreator.String()})),
|
||||
)
|
||||
|
|
|
@ -164,6 +164,9 @@ type exportContext struct {
|
|||
linkStateFilters *state.Filters
|
||||
isLinkProcess bool
|
||||
includeBackLinks bool
|
||||
relations map[string]struct{}
|
||||
setOfList map[string]struct{}
|
||||
objectTypes map[string]struct{}
|
||||
|
||||
*export
|
||||
}
|
||||
|
@ -182,7 +185,11 @@ func newExportContext(e *export, req pb.RpcObjectListExportRequest) *exportConte
|
|||
zip: req.Zip,
|
||||
linkStateFilters: pbFiltersToState(req.LinksStateFilters),
|
||||
includeBackLinks: req.IncludeBacklinks,
|
||||
export: e,
|
||||
setOfList: make(map[string]struct{}),
|
||||
objectTypes: make(map[string]struct{}),
|
||||
relations: make(map[string]struct{}),
|
||||
|
||||
export: e,
|
||||
}
|
||||
return ec
|
||||
}
|
||||
|
@ -201,6 +208,9 @@ func (e *exportContext) copy() *exportContext {
|
|||
isLinkProcess: e.isLinkProcess,
|
||||
linkStateFilters: e.linkStateFilters,
|
||||
includeBackLinks: e.includeBackLinks,
|
||||
relations: e.relations,
|
||||
setOfList: e.setOfList,
|
||||
objectTypes: e.objectTypes,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,70 +534,75 @@ func (e *exportContext) processFiles(ids []string) ([]string, error) {
|
|||
|
||||
func (e *exportContext) addDerivedObjects() error {
|
||||
processedObjects := make(map[string]struct{}, 0)
|
||||
allRelations, allTypes, allSetOfList, err := e.getRelationsAndTypes(e.docs, processedObjects)
|
||||
err := e.getRelationsAndTypes(e.docs, processedObjects)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
templateRelations, templateTypes, templateSetOfList, err := e.getTemplatesRelationsAndTypes(lo.Union(allTypes, allSetOfList), processedObjects)
|
||||
|
||||
err = e.getTemplatesRelationsAndTypes(processedObjects)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allRelations = lo.Union(allRelations, templateRelations)
|
||||
allTypes = lo.Union(allTypes, templateTypes)
|
||||
allSetOfList = lo.Union(allSetOfList, templateSetOfList)
|
||||
err = e.addRelationsAndTypes(allTypes, allRelations, allSetOfList)
|
||||
err = e.addRelationsAndTypes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *exportContext) getRelationsAndTypes(notProcessedObjects map[string]*Doc, processedObjects map[string]struct{}) ([]string, []string, []string, error) {
|
||||
allRelations, allTypes, allSetOfList, err := e.collectDerivedObjects(notProcessedObjects)
|
||||
func (e *exportContext) getRelationsAndTypes(notProcessedObjects map[string]*Doc, processedObjects map[string]struct{}) error {
|
||||
err := e.collectDerivedObjects(notProcessedObjects)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
// get derived objects only from types,
|
||||
// because relations currently have only system relations and object type
|
||||
if len(allTypes) > 0 || len(allSetOfList) > 0 {
|
||||
relations, objectTypes, setOfList, err := e.getDerivedObjectsForTypes(lo.Union(allTypes, allSetOfList), processedObjects)
|
||||
if len(e.objectTypes) > 0 || len(e.setOfList) > 0 {
|
||||
err = e.getDerivedObjectsForTypes(processedObjects)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
allRelations = lo.Union(allRelations, relations)
|
||||
allTypes = lo.Union(allTypes, objectTypes)
|
||||
allSetOfList = lo.Union(allSetOfList, setOfList)
|
||||
}
|
||||
return allRelations, allTypes, allSetOfList, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *exportContext) collectDerivedObjects(objects map[string]*Doc) ([]string, []string, []string, error) {
|
||||
var relations, objectsTypes, setOf []string
|
||||
func (e *exportContext) collectDerivedObjects(objects map[string]*Doc) error {
|
||||
for id := range objects {
|
||||
err := cache.Do(e.picker, id, func(b sb.SmartBlock) error {
|
||||
state := b.NewState().Copy().Filter(e.getStateFilters(id))
|
||||
relations = lo.Union(relations, getObjectRelations(state))
|
||||
objectRelations := getObjectRelations(state)
|
||||
fillObjectsMap(e.relations, objectRelations)
|
||||
details := state.CombinedDetails()
|
||||
if isObjectWithDataview(details) {
|
||||
dataviewRelations, err := getDataviewRelations(state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
relations = lo.Union(relations, dataviewRelations)
|
||||
fillObjectsMap(e.relations, dataviewRelations)
|
||||
}
|
||||
var objectTypes []string
|
||||
if details.Has(bundle.RelationKeyType) {
|
||||
objectTypeId := details.GetString(bundle.RelationKeyType)
|
||||
objectsTypes = lo.Union(objectsTypes, []string{objectTypeId})
|
||||
objectTypes = append(objectTypes, details.GetString(bundle.RelationKeyType))
|
||||
}
|
||||
if details.Has(bundle.RelationKeyTargetObjectType) {
|
||||
objectTypes = append(objectTypes, details.GetString(bundle.RelationKeyTargetObjectType))
|
||||
}
|
||||
fillObjectsMap(e.objectTypes, objectTypes)
|
||||
setOfList := details.GetStringList(bundle.RelationKeySetOf)
|
||||
setOf = lo.Union(setOf, setOfList)
|
||||
fillObjectsMap(e.setOfList, setOfList)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
return relations, objectsTypes, setOf, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillObjectsMap(dst map[string]struct{}, objectsToAdd []string) {
|
||||
for _, objectId := range objectsToAdd {
|
||||
dst[objectId] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
func getObjectRelations(state *state.State) []string {
|
||||
|
@ -619,33 +634,40 @@ func getDataviewRelations(state *state.State) ([]string, error) {
|
|||
return relations, err
|
||||
}
|
||||
|
||||
func (e *exportContext) getDerivedObjectsForTypes(allTypes []string, processedObjects map[string]struct{}) ([]string, []string, []string, error) {
|
||||
func (e *exportContext) getDerivedObjectsForTypes(processedObjects map[string]struct{}) error {
|
||||
notProceedTypes := make(map[string]*Doc)
|
||||
var relations, objectTypes []string
|
||||
for _, object := range allTypes {
|
||||
if _, ok := processedObjects[object]; ok {
|
||||
continue
|
||||
}
|
||||
notProceedTypes[object] = nil
|
||||
processedObjects[object] = struct{}{}
|
||||
for object := range e.objectTypes {
|
||||
e.fillNotProcessedTypes(processedObjects, object, notProceedTypes)
|
||||
}
|
||||
for object := range e.setOfList {
|
||||
e.fillNotProcessedTypes(processedObjects, object, notProceedTypes)
|
||||
}
|
||||
if len(notProceedTypes) == 0 {
|
||||
return relations, objectTypes, nil, nil
|
||||
return nil
|
||||
}
|
||||
relations, objectTypes, setOfList, err := e.getRelationsAndTypes(notProceedTypes, processedObjects)
|
||||
err := e.getRelationsAndTypes(notProceedTypes, processedObjects)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
return relations, objectTypes, setOfList, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *exportContext) getTemplatesRelationsAndTypes(allTypes []string, processedObjects map[string]struct{}) ([]string, []string, []string, error) {
|
||||
func (e *exportContext) fillNotProcessedTypes(processedObjects map[string]struct{}, object string, notProceedTypes map[string]*Doc) {
|
||||
if _, ok := processedObjects[object]; ok {
|
||||
return
|
||||
}
|
||||
notProceedTypes[object] = nil
|
||||
processedObjects[object] = struct{}{}
|
||||
}
|
||||
|
||||
func (e *exportContext) getTemplatesRelationsAndTypes(processedObjects map[string]struct{}) error {
|
||||
allTypes := lo.MapToSlice(e.objectTypes, func(key string, value struct{}) string { return key })
|
||||
templates, err := e.queryAndFilterObjectsByRelation(e.spaceId, allTypes, bundle.RelationKeyTargetObjectType)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil
|
||||
}
|
||||
if len(templates) == 0 {
|
||||
return nil, nil, nil, nil
|
||||
return nil
|
||||
}
|
||||
templatesToProcess := make(map[string]*Doc, len(templates))
|
||||
for _, template := range templates {
|
||||
|
@ -656,14 +678,18 @@ func (e *exportContext) getTemplatesRelationsAndTypes(allTypes []string, process
|
|||
templatesToProcess[id] = templateDoc
|
||||
}
|
||||
}
|
||||
templateRelations, templateType, templateSetOfList, err := e.getRelationsAndTypes(templatesToProcess, processedObjects)
|
||||
err = e.getRelationsAndTypes(templatesToProcess, processedObjects)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
return templateRelations, templateType, templateSetOfList, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *exportContext) addRelationsAndTypes(types, relations, setOfList []string) error {
|
||||
func (e *exportContext) addRelationsAndTypes() error {
|
||||
types := lo.MapToSlice(e.objectTypes, func(key string, value struct{}) string { return key })
|
||||
setOfList := lo.MapToSlice(e.setOfList, func(key string, value struct{}) string { return key })
|
||||
relations := lo.MapToSlice(e.relations, func(key string, value struct{}) string { return key })
|
||||
|
||||
err := e.addRelations(relations)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -947,10 +947,10 @@ func Test_docsForExport(t *testing.T) {
|
|||
relationKey := domain.RelationKey("key")
|
||||
storeFixture.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
domain.RelationKey(relationKey): domain.String("value"),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
relationKey: domain.String("value"),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
},
|
||||
})
|
||||
err := storeFixture.SpaceIndex(spaceId).UpdateObjectLinks(context.Background(), "id", []string{"id1"})
|
||||
|
@ -1016,10 +1016,10 @@ func Test_docsForExport(t *testing.T) {
|
|||
|
||||
storeFixture.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
domain.RelationKey(relationKey): domain.String("value"),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
relationKey: domain.String("value"),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String(relationKey),
|
||||
|
@ -1093,10 +1093,10 @@ func Test_docsForExport(t *testing.T) {
|
|||
|
||||
storeFixture.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
domain.RelationKey(relationKey): domain.String("value"),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
relationKey: domain.String("value"),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String(relationKey),
|
||||
|
@ -1172,10 +1172,10 @@ func Test_docsForExport(t *testing.T) {
|
|||
|
||||
storeFixture.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
domain.RelationKey(relationKey): domain.String(optionId),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyId: domain.String("id"),
|
||||
relationKey: domain.String(optionId),
|
||||
bundle.RelationKeyType: domain.String("objectType"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String(relationKey),
|
||||
|
@ -1967,6 +1967,106 @@ func Test_docsForExport(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(expCtx.docs))
|
||||
})
|
||||
t.Run("export template", func(t *testing.T) {
|
||||
// given
|
||||
storeFixture := objectstore.NewStoreFixture(t)
|
||||
objectTypeKey := "customObjectType"
|
||||
objectTypeUniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeObjectType, objectTypeKey)
|
||||
assert.Nil(t, err)
|
||||
|
||||
templateType := "templateType"
|
||||
templateObjectTypeUniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeObjectType, templateType)
|
||||
assert.Nil(t, err)
|
||||
|
||||
objectId := "objectId"
|
||||
storeFixture.AddObjects(t, spaceId, []objectstore.TestObject{
|
||||
{
|
||||
bundle.RelationKeyId: domain.String(objectId),
|
||||
bundle.RelationKeyName: domain.String("template"),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyTargetObjectType: domain.String(objectTypeKey),
|
||||
bundle.RelationKeyType: domain.String(templateType),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String(objectTypeKey),
|
||||
bundle.RelationKeyUniqueKey: domain.String(objectTypeUniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_objectType)),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyType: domain.String(objectTypeKey),
|
||||
},
|
||||
{
|
||||
bundle.RelationKeyId: domain.String(templateType),
|
||||
bundle.RelationKeyUniqueKey: domain.String(templateObjectTypeUniqueKey.Marshal()),
|
||||
bundle.RelationKeyLayout: domain.Int64(int64(model.ObjectType_objectType)),
|
||||
bundle.RelationKeySpaceId: domain.String(spaceId),
|
||||
bundle.RelationKeyType: domain.String(objectTypeKey),
|
||||
},
|
||||
})
|
||||
|
||||
smartBlockTest := smarttest.New(objectId)
|
||||
doc := smartBlockTest.NewState().SetDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
bundle.RelationKeyId: domain.String(objectId),
|
||||
bundle.RelationKeyType: domain.String(templateType),
|
||||
bundle.RelationKeyTargetObjectType: domain.String(objectTypeKey),
|
||||
}))
|
||||
doc.AddRelationLinks(&model.RelationLink{
|
||||
Key: bundle.RelationKeyId.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
})
|
||||
smartBlockTest.Doc = doc
|
||||
|
||||
objectType := smarttest.New(objectTypeKey)
|
||||
objectTypeDoc := objectType.NewState().SetDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
bundle.RelationKeyId: domain.String(objectTypeKey),
|
||||
bundle.RelationKeyType: domain.String(objectTypeKey),
|
||||
}))
|
||||
objectTypeDoc.AddRelationLinks(&model.RelationLink{
|
||||
Key: bundle.RelationKeyId.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
}, &model.RelationLink{
|
||||
Key: bundle.RelationKeyType.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
})
|
||||
objectType.Doc = objectTypeDoc
|
||||
|
||||
templateTypeObject := smarttest.New(templateType)
|
||||
templateTypeObjectDoc := objectType.NewState().SetDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
bundle.RelationKeyId: domain.String(templateType),
|
||||
bundle.RelationKeyType: domain.String(templateType),
|
||||
}))
|
||||
templateTypeObjectDoc.AddRelationLinks(&model.RelationLink{
|
||||
Key: bundle.RelationKeyId.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
}, &model.RelationLink{
|
||||
Key: bundle.RelationKeyType.String(),
|
||||
Format: model.RelationFormat_longtext,
|
||||
})
|
||||
templateTypeObject.Doc = templateTypeObjectDoc
|
||||
|
||||
objectGetter := mock_cache.NewMockObjectGetter(t)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), objectId).Return(smartBlockTest, nil)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), objectTypeKey).Return(objectType, nil)
|
||||
objectGetter.EXPECT().GetObject(context.Background(), templateType).Return(templateTypeObject, nil)
|
||||
|
||||
e := &export{
|
||||
objectStore: storeFixture,
|
||||
picker: objectGetter,
|
||||
}
|
||||
|
||||
expCtx := newExportContext(e, pb.RpcObjectListExportRequest{
|
||||
SpaceId: spaceId,
|
||||
ObjectIds: []string{objectId},
|
||||
IncludeNested: false,
|
||||
Format: model.Export_Protobuf,
|
||||
})
|
||||
|
||||
// when
|
||||
err = expCtx.docsForExport()
|
||||
|
||||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 3, len(expCtx.docs))
|
||||
})
|
||||
t.Run("add default object type and template from dataview", func(t *testing.T) {
|
||||
// given
|
||||
id := "id"
|
||||
|
|
|
@ -177,7 +177,6 @@ func getRelationDetails(name, key string, format float64) *domain.Details {
|
|||
details.SetFloat64(bundle.RelationKeyRelationFormat, format)
|
||||
details.SetString(bundle.RelationKeyName, name)
|
||||
details.SetString(bundle.RelationKeyRelationKey, key)
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_relation))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_relation))
|
||||
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, key)
|
||||
if err != nil {
|
||||
|
|
|
@ -258,7 +258,6 @@ func (ds *Service) getRelationDetails(databaseProperty property.DatabaseProperty
|
|||
details.SetString(bundle.RelationKeyName, name)
|
||||
details.SetString(bundle.RelationKeyRelationKey, key)
|
||||
details.SetInt64(bundle.RelationKeyCreatedDate, time.Now().Unix())
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_relation))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_relation))
|
||||
details.SetString(bundle.RelationKeySourceFilePath, databaseProperty.GetID())
|
||||
uniqueKey, err := domain.NewUniqueKey(sb.SmartBlockTypeRelation, key)
|
||||
|
|
|
@ -313,7 +313,6 @@ func (pt *Task) getRelationDetails(key string, name string, propObject property.
|
|||
details.SetInt64(bundle.RelationKeyRelationFormat, int64(propObject.GetFormat()))
|
||||
details.SetString(bundle.RelationKeyName, name)
|
||||
details.SetString(bundle.RelationKeyRelationKey, key)
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_relation))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_relation))
|
||||
details.SetString(bundle.RelationKeySourceFilePath, propObject.GetID())
|
||||
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, key)
|
||||
|
@ -563,7 +562,6 @@ func getDetailsForRelationOption(name, rel string) (string, *domain.Details) {
|
|||
details := domain.NewDetails()
|
||||
details.SetString(bundle.RelationKeyName, name)
|
||||
details.SetString(bundle.RelationKeyRelationKey, rel)
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_relationOption))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_relationOption))
|
||||
details.SetInt64(bundle.RelationKeyCreatedDate, time.Now().Unix())
|
||||
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelationOption, id)
|
||||
|
|
|
@ -65,7 +65,7 @@ func (s *SpaceImport) ProvideCollection(snapshots []*common.Snapshot,
|
|||
}
|
||||
|
||||
func (s *SpaceImport) objectShouldBeSkipped(item *common.Snapshot) bool {
|
||||
return item.Snapshot.SbType == smartblock.SmartBlockTypeSubObject || item.Snapshot.SbType == smartblock.SmartBlockTypeTemplate ||
|
||||
return item.Snapshot.SbType == smartblock.SmartBlockTypeSubObject ||
|
||||
item.Snapshot.SbType == smartblock.SmartBlockTypeRelation || item.Snapshot.SbType == smartblock.SmartBlockTypeObjectType ||
|
||||
item.Snapshot.SbType == smartblock.SmartBlockTypeRelationOption
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestSpaceImport_ProvideCollection(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
assert.Nil(t, collection)
|
||||
})
|
||||
t.Run("no widget object - add all objects (except template and subobjects) in Protobuf Import collection", func(t *testing.T) {
|
||||
t.Run("no widget object - add all objects (except subobjects) in Protobuf Import collection", func(t *testing.T) {
|
||||
// given
|
||||
p := SpaceImport{}
|
||||
params := &pb.RpcObjectImportRequestPbParams{NoCollection: false}
|
||||
|
@ -85,9 +85,10 @@ func TestSpaceImport_ProvideCollection(t *testing.T) {
|
|||
assert.Len(t, collection, 1)
|
||||
rootCollectionState := state.NewDocFromSnapshot("", collection[0].Snapshot.ToProto()).(*state.State)
|
||||
objectsInCollection := rootCollectionState.GetStoreSlice(template.CollectionStoreKey)
|
||||
assert.Len(t, objectsInCollection, 2)
|
||||
assert.Len(t, objectsInCollection, 3)
|
||||
assert.Equal(t, objectsInCollection[0], "id1")
|
||||
assert.Equal(t, objectsInCollection[1], "id4")
|
||||
assert.Equal(t, objectsInCollection[1], "id3")
|
||||
assert.Equal(t, objectsInCollection[2], "id4")
|
||||
})
|
||||
t.Run("widget with sets - add only sets in Protobuf Import collection", func(t *testing.T) {
|
||||
// given
|
||||
|
@ -106,6 +107,9 @@ func TestSpaceImport_ProvideCollection(t *testing.T) {
|
|||
Id: "id3",
|
||||
Snapshot: &common.SnapshotModel{
|
||||
SbType: smartblock2.SmartBlockTypeTemplate,
|
||||
Data: &common.StateSnapshot{
|
||||
ObjectTypes: []string{bundle.TypeKeyTemplate.URL()},
|
||||
},
|
||||
},
|
||||
},
|
||||
// page
|
||||
|
@ -191,6 +195,9 @@ func TestSpaceImport_ProvideCollection(t *testing.T) {
|
|||
Id: "id3",
|
||||
Snapshot: &common.SnapshotModel{
|
||||
SbType: smartblock2.SmartBlockTypeTemplate,
|
||||
Data: &common.StateSnapshot{
|
||||
ObjectTypes: []string{bundle.TypeKeyTemplate.URL()},
|
||||
},
|
||||
},
|
||||
},
|
||||
// page
|
||||
|
@ -277,6 +284,9 @@ func TestSpaceImport_ProvideCollection(t *testing.T) {
|
|||
Id: "id3",
|
||||
Snapshot: &common.SnapshotModel{
|
||||
SbType: smartblock2.SmartBlockTypeTemplate,
|
||||
Data: &common.StateSnapshot{
|
||||
ObjectTypes: []string{bundle.TypeKeyTemplate.URL()},
|
||||
},
|
||||
},
|
||||
},
|
||||
// favorite page
|
||||
|
|
|
@ -41,7 +41,6 @@ func (s *service) createChatDerived(ctx context.Context, space clientspace.Space
|
|||
}
|
||||
|
||||
createState := state.NewDocWithUniqueKey("", nil, key).(*state.State)
|
||||
details.Set(bundle.RelationKeyResolvedLayout, domain.Int64(int64(model.ObjectType_chatDerived)))
|
||||
details.Set(bundle.RelationKeyLayout, domain.Int64(int64(model.ObjectType_chatDerived)))
|
||||
createState.SetDetails(details)
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ func (s *service) prepareDetailsForInstallingObject(
|
|||
|
||||
switch uk.SmartblockType() {
|
||||
case coresb.SmartBlockTypeBundledObjectType, coresb.SmartBlockTypeObjectType:
|
||||
relationKeys, isAlreadyFilled, err := relationutils.FillRecommendedRelations(ctx, spc, details)
|
||||
relationKeys, isAlreadyFilled, err := relationutils.FillRecommendedRelations(ctx, spc, details, domain.TypeKey(uk.InternalKey()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fill recommended relations: %w", err)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ func (s *service) createObjectType(ctx context.Context, space clientspace.Space,
|
|||
object.SetInt64(bundle.RelationKeyRecommendedLayout, int64(model.ObjectType_basic))
|
||||
}
|
||||
|
||||
keys, isAlreadyFilled, err := relationutils.FillRecommendedRelations(ctx, space, object)
|
||||
keys, isAlreadyFilled, err := relationutils.FillRecommendedRelations(ctx, space, object, domain.TypeKey(uniqueKey.InternalKey()))
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("fill recommended relations: %w", err)
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ func (s *service) createObjectType(ctx context.Context, space clientspace.Space,
|
|||
}
|
||||
|
||||
object.SetString(bundle.RelationKeyId, id)
|
||||
object.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_objectType))
|
||||
object.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_objectType))
|
||||
|
||||
createState := state.NewDocWithUniqueKey("", nil, uniqueKey).(*state.State)
|
||||
|
|
|
@ -59,7 +59,6 @@ func (s *service) createRelation(ctx context.Context, space clientspace.Space, d
|
|||
}
|
||||
// todo: check the existence of objectTypes in space. InstallBundledObjects should be called same as for recommendedRelations on type creation
|
||||
|
||||
object.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_relation))
|
||||
object.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_relation))
|
||||
|
||||
createState := state.NewDocWithUniqueKey("", nil, uniqueKey).(*state.State)
|
||||
|
|
|
@ -36,7 +36,6 @@ func (s *service) createRelationOption(ctx context.Context, space clientspace.Sp
|
|||
|
||||
object = details.Copy()
|
||||
object.SetString(bundle.RelationKeyUniqueKey, uniqueKey.Marshal())
|
||||
object.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_relationOption))
|
||||
object.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_relationOption))
|
||||
|
||||
createState := state.NewDocWithUniqueKey("", nil, uniqueKey).(*state.State)
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/space/clientspace"
|
||||
|
@ -58,7 +57,6 @@ func (s *service) CreateSmartBlockFromStateInSpaceWithOptions(
|
|||
if createState == nil {
|
||||
createState = state.NewDoc("", nil).(*state.State)
|
||||
}
|
||||
startTime := time.Now()
|
||||
// priority:
|
||||
// 1. details
|
||||
// 2. createState
|
||||
|
@ -71,11 +69,6 @@ func (s *service) CreateSmartBlockFromStateInSpaceWithOptions(
|
|||
|
||||
createState.SetDetailAndBundledRelation(bundle.RelationKeySpaceId, domain.String(spc.Id()))
|
||||
|
||||
ev := &metrics.CreateObjectEvent{
|
||||
SetDetailsMs: time.Since(startTime).Milliseconds(),
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, eventCreate, ev)
|
||||
initFunc := func(id string) *smartblock.InitContext {
|
||||
createState.SetRootId(id)
|
||||
return &smartblock.InitContext{
|
||||
|
@ -97,10 +90,6 @@ func (s *service) CreateSmartBlockFromStateInSpaceWithOptions(
|
|||
sb.Unlock()
|
||||
id = sb.Id()
|
||||
|
||||
ev.SmartblockCreateMs = time.Since(startTime).Milliseconds() - ev.SetDetailsMs - ev.WorkspaceCreateMs - ev.GetWorkspaceBlockWaitMs
|
||||
ev.SmartblockType = int(sbType)
|
||||
ev.ObjectId = id
|
||||
metrics.Service.Send(ev)
|
||||
return id, newDetails, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/files/fileobject"
|
||||
"github.com/anyproto/anytype-heart/core/files/fileuploader"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
|
@ -184,27 +183,22 @@ func (s *Service) GetObjectByFullID(ctx context.Context, id domain.FullID) (sb s
|
|||
|
||||
func (s *Service) OpenBlock(sctx session.Context, id domain.FullID, includeRelationsAsDependentObjects bool) (obj *model.ObjectView, err error) {
|
||||
id = s.resolveFullId(id)
|
||||
startTime := time.Now()
|
||||
err = s.DoFullId(id, func(ob smartblock.SmartBlock) error {
|
||||
if includeRelationsAsDependentObjects {
|
||||
ob.EnabledRelationAsDependentObjects()
|
||||
}
|
||||
afterSmartBlockTime := time.Now()
|
||||
|
||||
ob.RegisterSession(sctx)
|
||||
|
||||
afterDataviewTime := time.Now()
|
||||
st := ob.NewState()
|
||||
|
||||
st.SetLocalDetail(bundle.RelationKeyLastOpenedDate, domain.Int64(time.Now().Unix()))
|
||||
if err = ob.Apply(st, smartblock.NoHistory, smartblock.NoEvent, smartblock.SkipIfNoChanges, smartblock.KeepInternalFlags, smartblock.IgnoreNoPermissions); err != nil {
|
||||
log.Errorf("failed to update lastOpenedDate: %s", err)
|
||||
}
|
||||
afterApplyTime := time.Now()
|
||||
if obj, err = ob.Show(); err != nil {
|
||||
return fmt.Errorf("show: %w", err)
|
||||
}
|
||||
afterShowTime := time.Now()
|
||||
|
||||
if err != nil && !errors.Is(err, treestorage.ErrUnknownTreeId) {
|
||||
log.Errorf("failed to watch status for object %s: %s", id, err)
|
||||
|
@ -214,16 +208,6 @@ func (s *Service) OpenBlock(sctx session.Context, id domain.FullID, includeRelat
|
|||
v.InjectVirtualBlocks(id.ObjectID, obj)
|
||||
}
|
||||
|
||||
afterHashesTime := time.Now()
|
||||
metrics.Service.Send(&metrics.OpenBlockEvent{
|
||||
ObjectId: id.ObjectID,
|
||||
GetBlockMs: afterSmartBlockTime.Sub(startTime).Milliseconds(),
|
||||
DataviewMs: afterDataviewTime.Sub(afterSmartBlockTime).Milliseconds(),
|
||||
ApplyMs: afterApplyTime.Sub(afterDataviewTime).Milliseconds(),
|
||||
ShowMs: afterShowTime.Sub(afterApplyTime).Milliseconds(),
|
||||
FileWatcherMs: afterHashesTime.Sub(afterShowTime).Milliseconds(),
|
||||
SmartblockType: int(ob.Type()),
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -89,7 +89,6 @@ func (d *date) ReadDoc(context.Context, ChangeReceiver, bool) (doc state.Doc, er
|
|||
s := state.NewDoc(d.id, nil).(*state.State)
|
||||
template.InitTemplate(s,
|
||||
template.WithTitle,
|
||||
template.WithDefaultFeaturedRelations,
|
||||
template.WithAllBlocksEditsRestricted,
|
||||
)
|
||||
s.SetDetails(details)
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/template"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/files"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
|
@ -31,6 +32,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/reflection"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
||||
|
@ -331,7 +333,6 @@ func (s *source) buildState() (doc state.Doc, err error) {
|
|||
// we need to have required internal relations for all objects, including system
|
||||
st.AddBundledRelationLinks(bundle.RequiredInternalRelations...)
|
||||
if s.Type() == smartblock.SmartBlockTypePage || s.Type() == smartblock.SmartBlockTypeProfilePage {
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyBacklinks)(st)
|
||||
template.WithRelations([]domain.RelationKey{bundle.RelationKeyBacklinks})(st)
|
||||
}
|
||||
|
||||
|
@ -377,6 +378,20 @@ type PushChangeParams struct {
|
|||
}
|
||||
|
||||
func (s *source) PushChange(params PushChangeParams) (id string, err error) {
|
||||
for _, change := range params.Changes {
|
||||
name := reflection.GetChangeContent(change.Value)
|
||||
if name == "" {
|
||||
log.Errorf("can't detect change content for %s", change.Value)
|
||||
} else {
|
||||
ev := &metrics.ChangeEvent{
|
||||
ChangeName: name,
|
||||
SbType: s.smartblockType.String(),
|
||||
Count: 1,
|
||||
}
|
||||
metrics.Service.SendSampled(ev)
|
||||
}
|
||||
}
|
||||
|
||||
if params.Time.IsZero() {
|
||||
params.Time = time.Now()
|
||||
}
|
||||
|
|
|
@ -91,11 +91,9 @@ func (s *store) ReadDoc(ctx context.Context, receiver ChangeReceiver, empty bool
|
|||
switch s.sbType {
|
||||
case smartblock.SmartBlockTypeChatDerivedObject:
|
||||
st.SetObjectTypeKey(bundle.TypeKeyChatDerived)
|
||||
st.SetDetailAndBundledRelation(bundle.RelationKeyResolvedLayout, domain.Int64(int64(model.ObjectType_chatDerived)))
|
||||
st.SetDetailAndBundledRelation(bundle.RelationKeyLayout, domain.Int64(int64(model.ObjectType_chatDerived)))
|
||||
case smartblock.SmartBlockTypeAccountObject:
|
||||
st.SetObjectTypeKey(bundle.TypeKeyProfile)
|
||||
st.SetDetailAndBundledRelation(bundle.RelationKeyResolvedLayout, domain.Int64(int64(model.ObjectType_profile)))
|
||||
st.SetDetailAndBundledRelation(bundle.RelationKeyLayout, domain.Int64(int64(model.ObjectType_profile)))
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported smartblock type: %v", s.sbType)
|
||||
|
|
|
@ -44,9 +44,11 @@ var (
|
|||
log = logging.Logger("template")
|
||||
|
||||
templateIsPreferableRelationKeys = []domain.RelationKey{
|
||||
bundle.RelationKeyFeaturedRelations, bundle.RelationKeyResolvedLayout,
|
||||
bundle.RelationKeyIconEmoji, bundle.RelationKeyCoverId,
|
||||
bundle.RelationKeySourceObject, bundle.RelationKeySetOf,
|
||||
bundle.RelationKeyLayout,
|
||||
bundle.RelationKeyIconEmoji,
|
||||
bundle.RelationKeyCoverId,
|
||||
bundle.RelationKeySourceObject,
|
||||
bundle.RelationKeySetOf,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -178,13 +180,14 @@ func extractTargetDetails(originDetails *domain.Details, templateDetails *domain
|
|||
return targetDetails
|
||||
}
|
||||
for key, originalVal := range originDetails.Iterate() {
|
||||
if key == bundle.RelationKeyLayout {
|
||||
// layout detail should be removed, as resolvedLayout should be derived from template state
|
||||
targetDetails.Delete(key)
|
||||
continue
|
||||
}
|
||||
templateVal := templateDetails.Get(key)
|
||||
if templateVal.Ok() {
|
||||
inTemplateEmpty := templateVal.IsEmpty()
|
||||
if key == bundle.RelationKeyResolvedLayout {
|
||||
// layout = 0 is actually basic layout, so it counts
|
||||
inTemplateEmpty = false
|
||||
}
|
||||
inOriginEmpty := originalVal.IsEmpty()
|
||||
templateValueShouldBePreferred := lo.Contains(templateIsPreferableRelationKeys, key)
|
||||
if !inTemplateEmpty && (inOriginEmpty || templateValueShouldBePreferred) {
|
||||
|
@ -236,6 +239,7 @@ func (s *service) buildState(sb smartblock.SmartBlock) (st *state.State, err err
|
|||
bundle.RelationKeyTemplateIsBundled,
|
||||
bundle.RelationKeyOrigin,
|
||||
bundle.RelationKeyAddedDate,
|
||||
bundle.RelationKeyFeaturedRelations,
|
||||
)
|
||||
st.SetDetailAndBundledRelation(bundle.RelationKeySourceObject, domain.String(sb.Id()))
|
||||
// original created timestamp is used to set creationDate for imported objects, not for template-based objects
|
||||
|
@ -427,9 +431,7 @@ func (s *service) SetDefaultTemplateInType(ctx context.Context, typeId, template
|
|||
func (s *service) createBlankTemplateState(typeId domain.FullID, layout model.ObjectTypeLayout) (st *state.State) {
|
||||
st = state.NewDoc(BlankTemplateId, nil).NewState()
|
||||
template.InitTemplate(st, template.WithEmpty,
|
||||
template.WithDefaultFeaturedRelations,
|
||||
template.WithFeaturedRelations,
|
||||
template.WithAddedFeaturedRelation(bundle.RelationKeyTag),
|
||||
template.WithFeaturedRelationsBlock,
|
||||
template.WithDetail(bundle.RelationKeyTag, domain.StringList(nil)),
|
||||
template.WithTitle,
|
||||
)
|
||||
|
|
|
@ -170,7 +170,6 @@ func TestService_CreateTemplateStateWithDetails(t *testing.T) {
|
|||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, BlankTemplateId, st.RootId())
|
||||
assert.Contains(t, st.Details().GetStringList(bundle.RelationKeyFeaturedRelations), bundle.RelationKeyTag.String())
|
||||
assert.True(t, st.Details().Has(bundle.RelationKeyTag))
|
||||
})
|
||||
}
|
||||
|
@ -255,7 +254,6 @@ func TestCreateTemplateStateFromSmartBlock(t *testing.T) {
|
|||
|
||||
// then
|
||||
assert.Equal(t, BlankTemplateId, st.RootId())
|
||||
assert.Contains(t, st.Details().GetStringList(bundle.RelationKeyFeaturedRelations), bundle.RelationKeyTag.String())
|
||||
assert.True(t, st.Details().Has(bundle.RelationKeyTag))
|
||||
})
|
||||
|
||||
|
@ -394,15 +392,12 @@ func TestExtractTargetDetails(t *testing.T) {
|
|||
OriginValue, TemplateValue domain.Value
|
||||
OriginLeft bool
|
||||
}{
|
||||
{Key: bundle.RelationKeyResolvedLayout, OriginValue: domain.Int64(0), TemplateValue: domain.Int64(1), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyResolvedLayout, OriginValue: domain.Int64(5), TemplateValue: domain.Int64(0), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyResolvedLayout, OriginValue: domain.Int64(3), TemplateValue: domain.Int64(3), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyLayout, OriginValue: domain.Int64(0), TemplateValue: domain.Int64(1), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyLayout, OriginValue: domain.Int64(5), TemplateValue: domain.Int64(0), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyLayout, OriginValue: domain.Int64(3), TemplateValue: domain.Int64(3), OriginLeft: false},
|
||||
{Key: bundle.RelationKeySourceObject, OriginValue: domain.String(""), TemplateValue: domain.String("s1"), OriginLeft: false},
|
||||
{Key: bundle.RelationKeySourceObject, OriginValue: domain.String("s2"), TemplateValue: domain.String(""), OriginLeft: true},
|
||||
{Key: bundle.RelationKeySourceObject, OriginValue: domain.String("s0"), TemplateValue: domain.String("s3"), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyFeaturedRelations, OriginValue: domain.StringList([]string{"tag"}), TemplateValue: domain.StringList([]string{}), OriginLeft: true},
|
||||
{Key: bundle.RelationKeyFeaturedRelations, OriginValue: domain.StringList([]string{}), TemplateValue: domain.StringList([]string{"tag", "type"}), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyFeaturedRelations, OriginValue: domain.StringList([]string{"type"}), TemplateValue: domain.StringList([]string{"tag"}), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyName, OriginValue: domain.String("orig"), TemplateValue: domain.String(""), OriginLeft: true},
|
||||
{Key: bundle.RelationKeyName, OriginValue: domain.String(""), TemplateValue: domain.String("tmpl"), OriginLeft: false},
|
||||
{Key: bundle.RelationKeyName, OriginValue: domain.String("orig"), TemplateValue: domain.String("tmpl"), OriginLeft: true},
|
||||
|
|
|
@ -65,7 +65,7 @@ func ExportTree(ctx context.Context, params ExportParams) error {
|
|||
converter = params.Converter
|
||||
changes []*treechangeproto.RawTreeChangeWithId
|
||||
)
|
||||
err = writeTree.IterateRoot(
|
||||
err = params.Readable.IterateRoot(
|
||||
func(change *objecttree.Change, decrypted []byte) (any, error) {
|
||||
return converter.Unmarshall(change.DataType, decrypted)
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@ type ImportResult struct {
|
|||
List list.AclList
|
||||
Storage objecttree.Storage
|
||||
FolderPath string
|
||||
Store anystore.DB
|
||||
}
|
||||
|
||||
func (i ImportResult) CreateReadableTree(fullTree bool, beforeId string) (objecttree.ReadableObjectTree, error) {
|
||||
|
@ -48,11 +49,10 @@ func ImportStorage(ctx context.Context, path string) (res ImportResult, err erro
|
|||
if err = ziputil.UnzipFolder(path, targetDir); err != nil {
|
||||
return
|
||||
}
|
||||
anyStore, err := anystore.Open(ctx, targetDir, nil)
|
||||
anyStore, err := anystore.Open(ctx, filepath.Join(targetDir, "db"), nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer anyStore.Close()
|
||||
var (
|
||||
aclId string
|
||||
treeId string
|
||||
|
@ -92,5 +92,6 @@ func ImportStorage(ctx context.Context, path string) (res ImportResult, err erro
|
|||
List: acl,
|
||||
Storage: treeStorage,
|
||||
FolderPath: targetDir,
|
||||
Store: anyStore,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -43,10 +43,6 @@ func (e *treeExporter) Export(ctx context.Context, path string, tree objecttree.
|
|||
defer func() {
|
||||
_ = os.RemoveAll(exportDirPath)
|
||||
}()
|
||||
err = os.Mkdir(dbPath, 0755)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
anyStore, err := anystore.Open(ctx, dbPath, nil)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -76,8 +72,7 @@ func (e *treeExporter) Export(ctx context.Context, path string, tree objecttree.
|
|||
e.log.Printf("can't fetch localstore info: %v", err)
|
||||
} else {
|
||||
if len(data) > 0 {
|
||||
// TODO: [storage] fix details, take from main
|
||||
// data[0].Details = transform(data[0].Details, e.anonymized, anonymize.Struct)
|
||||
data[0].Details = transform(data[0].Details, e.anonymized, anonymize.Details)
|
||||
data[0].Snippet = transform(data[0].Snippet, e.anonymized, anonymize.Text)
|
||||
for i, r := range data[0].Relations {
|
||||
data[0].Relations[i] = transform(r, e.anonymized, anonymize.Relation)
|
||||
|
|
|
@ -88,17 +88,14 @@ func (f *file) Details(ctx context.Context) (*domain.Details, domain.TypeKey, er
|
|||
|
||||
if meta.Media == "application/pdf" {
|
||||
typeKey = bundle.TypeKeyFile
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_pdf))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_pdf))
|
||||
}
|
||||
if strings.HasPrefix(meta.Media, "video") {
|
||||
typeKey = bundle.TypeKeyVideo
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_video))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_video))
|
||||
}
|
||||
|
||||
if strings.HasPrefix(meta.Media, "audio") {
|
||||
details.Set(bundle.RelationKeyResolvedLayout, domain.Int64(model.ObjectType_audio))
|
||||
details.Set(bundle.RelationKeyLayout, domain.Int64(model.ObjectType_audio))
|
||||
if audioDetails, err := f.audioDetails(ctx); err == nil {
|
||||
details = details.Merge(audioDetails)
|
||||
|
@ -107,7 +104,6 @@ func (f *file) Details(ctx context.Context) (*domain.Details, domain.TypeKey, er
|
|||
}
|
||||
if filepath.Ext(meta.Name) == constant.SvgExt {
|
||||
typeKey = bundle.TypeKeyImage
|
||||
details.Set(bundle.RelationKeyResolvedLayout, domain.Int64(model.ObjectType_image))
|
||||
details.Set(bundle.RelationKeyLayout, domain.Int64(model.ObjectType_image))
|
||||
}
|
||||
|
||||
|
@ -144,7 +140,6 @@ func calculateCommonDetails(
|
|||
det := domain.NewDetails()
|
||||
det.SetString(bundle.RelationKeyFileId, fileId.String())
|
||||
det.SetBool(bundle.RelationKeyIsReadonly, false)
|
||||
det.SetInt64(bundle.RelationKeyResolvedLayout, int64(layout))
|
||||
det.SetInt64(bundle.RelationKeyLayout, int64(layout))
|
||||
det.SetFloat64(bundle.RelationKeyLastModifiedDate, float64(lastModifiedDate))
|
||||
return det
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestFile_Details(t *testing.T) {
|
|||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyImage, typeKey)
|
||||
assert.Equal(t, int64(model.ObjectType_image), details.GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
assert.Equal(t, int64(model.ObjectType_image), details.GetInt64(bundle.RelationKeyLayout))
|
||||
assert.Equal(t, "svg", details.GetString(bundle.RelationKeyFileExt))
|
||||
assert.Equal(t, "image", details.GetString(bundle.RelationKeyName))
|
||||
assert.Equal(t, "id", details.GetString(bundle.RelationKeyFileId))
|
||||
|
@ -49,7 +49,7 @@ func TestFile_Details(t *testing.T) {
|
|||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyFile, typeKey)
|
||||
assert.Equal(t, int64(model.ObjectType_file), details.GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
assert.Equal(t, int64(model.ObjectType_file), details.GetInt64(bundle.RelationKeyLayout))
|
||||
assert.Equal(t, "txt", details.GetString(bundle.RelationKeyFileExt))
|
||||
assert.Equal(t, "file", details.GetString(bundle.RelationKeyName))
|
||||
assert.Equal(t, "id", details.GetString(bundle.RelationKeyFileId))
|
||||
|
@ -70,7 +70,7 @@ func TestFile_Details(t *testing.T) {
|
|||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyAudio, typeKey)
|
||||
assert.Equal(t, int64(model.ObjectType_audio), details.GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
assert.Equal(t, int64(model.ObjectType_audio), details.GetInt64(bundle.RelationKeyLayout))
|
||||
assert.Equal(t, "mp3", details.GetString(bundle.RelationKeyFileExt))
|
||||
assert.Equal(t, "file", details.GetString(bundle.RelationKeyName))
|
||||
assert.Equal(t, "id", details.GetString(bundle.RelationKeyFileId))
|
||||
|
@ -91,7 +91,7 @@ func TestFile_Details(t *testing.T) {
|
|||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyVideo, typeKey)
|
||||
assert.Equal(t, int64(model.ObjectType_video), details.GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
assert.Equal(t, int64(model.ObjectType_video), details.GetInt64(bundle.RelationKeyLayout))
|
||||
assert.Equal(t, "mp4", details.GetString(bundle.RelationKeyFileExt))
|
||||
assert.Equal(t, "file", details.GetString(bundle.RelationKeyName))
|
||||
assert.Equal(t, "id", details.GetString(bundle.RelationKeyFileId))
|
||||
|
@ -112,7 +112,7 @@ func TestFile_Details(t *testing.T) {
|
|||
// then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, bundle.TypeKeyFile, typeKey)
|
||||
assert.Equal(t, int64(model.ObjectType_pdf), details.GetInt64(bundle.RelationKeyResolvedLayout))
|
||||
assert.Equal(t, int64(model.ObjectType_pdf), details.GetInt64(bundle.RelationKeyLayout))
|
||||
assert.Equal(t, "pdf", details.GetString(bundle.RelationKeyFileExt))
|
||||
assert.Equal(t, "file", details.GetString(bundle.RelationKeyName))
|
||||
assert.Equal(t, "id", details.GetString(bundle.RelationKeyFileId))
|
||||
|
|
|
@ -16,8 +16,7 @@ func InitEmptyFileState(st *state.State) {
|
|||
template.InitTemplate(st,
|
||||
template.WithEmpty,
|
||||
template.WithTitle,
|
||||
template.WithDefaultFeaturedRelations,
|
||||
template.WithFeaturedRelations,
|
||||
template.WithFeaturedRelationsBlock,
|
||||
template.WithAllBlocksEditsRestricted,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -24,16 +23,6 @@ type indexerFixture struct {
|
|||
objectStoreFixture *objectstore.StoreFixture
|
||||
}
|
||||
|
||||
type dummyAccountService struct{}
|
||||
|
||||
func (s dummyAccountService) MyParticipantId(spaceId string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s dummyAccountService) Init(_ *app.App) error { return nil }
|
||||
|
||||
func (s dummyAccountService) Name() string { return "dummyAccountService" }
|
||||
|
||||
func newIndexerFixture(t *testing.T) *indexerFixture {
|
||||
objectStore := objectstore.NewStoreFixture(t)
|
||||
fileService := mock_files.NewMockService(t)
|
||||
|
|
|
@ -223,10 +223,12 @@ func (s *service) ensureNotSyncedFilesAddedToQueue() error {
|
|||
|
||||
for _, record := range records {
|
||||
fullId := extractFullFileIdFromDetails(record.Details)
|
||||
id := record.Details.GetString(bundle.RelationKeyId)
|
||||
err := s.addToSyncQueue(id, fullId, false, false)
|
||||
if err != nil {
|
||||
log.Errorf("add to sync queue: %v", err)
|
||||
if record.Details.GetString(bundle.RelationKeyCreator) == s.accountService.MyParticipantId(fullId.SpaceId) {
|
||||
id := record.Details.GetString(bundle.RelationKeyId)
|
||||
err := s.addToSyncQueue(id, fullId, false, false)
|
||||
if err != nil {
|
||||
log.Errorf("add to sync queue: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,7 +350,6 @@ func (s *service) makeInitialDetails(fileId domain.FileId, origin objectorigin.O
|
|||
details := domain.NewDetails()
|
||||
details.SetString(bundle.RelationKeyFileId, fileId.String())
|
||||
// Use general file layout. It will be changed for proper layout after indexing
|
||||
details.SetInt64(bundle.RelationKeyResolvedLayout, int64(model.ObjectType_file))
|
||||
details.SetInt64(bundle.RelationKeyLayout, int64(model.ObjectType_file))
|
||||
details.SetInt64(bundle.RelationKeyFileIndexingStatus, int64(model.FileIndexingStatus_NotIndexed))
|
||||
details.SetInt64(bundle.RelationKeySyncStatus, int64(domain.ObjectSyncStatusQueued))
|
||||
|
|
|
@ -53,6 +53,16 @@ type fixture struct {
|
|||
*service
|
||||
}
|
||||
|
||||
type dummyAccountService struct{}
|
||||
|
||||
func (s *dummyAccountService) MyParticipantId(spaceId string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *dummyAccountService) Init(_ *app.App) error { return nil }
|
||||
|
||||
func (s *dummyAccountService) Name() string { return "dummyAccountService" }
|
||||
|
||||
type dummyConfig struct{}
|
||||
|
||||
func (c *dummyConfig) IsLocalOnlyMode() bool {
|
||||
|
@ -108,6 +118,7 @@ func newFixture(t *testing.T) *fixture {
|
|||
|
||||
a := new(app.App)
|
||||
a.Register(&dummyConfig{})
|
||||
a.Register(&dummyAccountService{})
|
||||
a.Register(dataStoreProvider)
|
||||
a.Register(fileStore)
|
||||
a.Register(objectStore)
|
||||
|
@ -126,7 +137,6 @@ func newFixture(t *testing.T) *fixture {
|
|||
a.Register(testutil.PrepareMock(ctx, a, wallet))
|
||||
a.Register(&config.Config{DisableFileConfig: true, NetworkMode: pb.RpcAccount_DefaultConfig, PeferYamuxTransport: true})
|
||||
a.Register(&dummyObjectArchiver{})
|
||||
a.Register(&dummyAccountService{})
|
||||
|
||||
err = a.Start(ctx)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/h2non/filetype"
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/cache"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
|
@ -540,12 +540,12 @@ func (u *uploader) getOrCreateFileObject(ctx context.Context, addResult *files.A
|
|||
}
|
||||
|
||||
func (u *uploader) detectType(buf *fileReader) model.BlockContentFileType {
|
||||
b, err := buf.Peek(8192)
|
||||
if err != nil && err != io.EOF {
|
||||
mime, err := mimetype.DetectReader(buf)
|
||||
if err != nil {
|
||||
log.With("error", err).Error("detect MIME")
|
||||
return model.BlockContentFile_File
|
||||
}
|
||||
tp, _ := filetype.Match(b)
|
||||
return file.DetectTypeByMIME(u.name, tp.MIME.Value)
|
||||
return file.DetectTypeByMIME(u.name, mime.String())
|
||||
}
|
||||
|
||||
type FileComponent interface {
|
||||
|
|
|
@ -4,9 +4,8 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/h2non/filetype"
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
)
|
||||
|
||||
type AddOption func(*AddOptions)
|
||||
|
@ -70,13 +69,8 @@ func (s *service) normalizeOptions(opts *AddOptions) error {
|
|||
return fmt.Errorf("failed to seek underlying reader: %w", err)
|
||||
}
|
||||
|
||||
t, err := filetype.Match(data)
|
||||
if err != nil {
|
||||
log.Warnf("filetype failed to match: %s", err)
|
||||
opts.Media = http.DetectContentType(data)
|
||||
} else {
|
||||
opts.Media = t.MIME.Value
|
||||
}
|
||||
mime := mimetype.Detect(data)
|
||||
opts.Media = mime.String()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -233,7 +233,8 @@ func (c *flatStoreGarbageCollector) CollectGarbage(ctx context.Context) error {
|
|||
}
|
||||
|
||||
c.flatStore.sendLocalBytesUsageEvent(ctx)
|
||||
return results.Close()
|
||||
results.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func newFlatStoreGarbageCollector(flatStore *flatStore) LocalStoreGarbageCollector {
|
||||
|
|
|
@ -56,7 +56,6 @@ func DownloadManifest(url string, checkWhitelist bool) (info *model.ManifestInfo
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
schemaResp := schemaResponse{}
|
||||
err = json.Unmarshal(raw, &schemaResp)
|
||||
if err != nil {
|
||||
|
@ -119,7 +118,7 @@ func getRawJson(url string) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Close = true
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
_ "embed"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -11,8 +12,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
)
|
||||
|
||||
const port = ":7070"
|
||||
|
||||
//go:embed testdata/schema.json
|
||||
var schemaJSON []byte
|
||||
|
||||
|
@ -37,13 +36,13 @@ func TestIsInWhitelist(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDownloadManifestAndValidateSchema(t *testing.T) {
|
||||
schema := schemaResponse{Schema: "http://localhost" + port + "/schema.json"}
|
||||
server := startHttpServer()
|
||||
defer server.Shutdown(nil)
|
||||
defer server.Close()
|
||||
schema := schemaResponse{Schema: server.URL + "/schema.json"}
|
||||
|
||||
t.Run("download knowledge base manifest", func(t *testing.T) {
|
||||
// given
|
||||
url := "http://localhost" + port + "/manifest.json"
|
||||
url := server.URL + "/manifest.json"
|
||||
|
||||
// when
|
||||
info, err := DownloadManifest(url, false)
|
||||
|
@ -116,7 +115,7 @@ func TestDownloadManifestAndValidateSchema(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func startHttpServer() *http.Server {
|
||||
func startHttpServer() *httptest.Server {
|
||||
handler := http.NewServeMux()
|
||||
handler.HandleFunc("/manifest.json", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
@ -128,9 +127,7 @@ func startHttpServer() *http.Server {
|
|||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write(schemaJSON)
|
||||
})
|
||||
server := &http.Server{Addr: port, Handler: handler}
|
||||
go server.ListenAndServe()
|
||||
return server
|
||||
return httptest.NewServer(handler)
|
||||
}
|
||||
|
||||
func buildInfo() *model.ManifestInfo {
|
||||
|
|
|
@ -438,9 +438,10 @@ func (i *indexer) reindexIDs(ctx context.Context, space smartblock.Space, reinde
|
|||
func (i *indexer) reindexOutdatedObjects(ctx context.Context, space clientspace.Space) (toReindex, success int, err error) {
|
||||
store := i.store.SpaceIndex(space.Id())
|
||||
var entries []headstorage.HeadsEntry
|
||||
|
||||
err = space.Storage().HeadStorage().IterateEntries(ctx, headstorage.IterOpts{}, func(entry headstorage.HeadsEntry) (bool, error) {
|
||||
// skipping Acl
|
||||
if entry.CommonSnapshot != "" {
|
||||
if entry.CommonSnapshot != "" && entry.Id != space.Storage().StateStorage().SettingsId() {
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
return true, nil
|
||||
|
@ -558,15 +559,6 @@ func (i *indexer) logFinishedReindexStat(reindexType metrics.ReindexType, totalI
|
|||
} else {
|
||||
log.Info(msg)
|
||||
}
|
||||
|
||||
if metrics.Enabled {
|
||||
metrics.Service.Send(&metrics.ReindexEvent{
|
||||
ReindexType: reindexType,
|
||||
Total: totalIds,
|
||||
Succeed: succeedIds,
|
||||
SpentMs: int(spent.Milliseconds()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (i *indexer) RemoveIndexes(spaceId string) error {
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/spaceindex"
|
||||
)
|
||||
|
@ -117,7 +116,6 @@ func (i *spaceIndexer) Index(info smartblock.DocInfo, options ...smartblock.Inde
|
|||
|
||||
func (i *spaceIndexer) index(ctx context.Context, info smartblock.DocInfo, options ...smartblock.IndexOption) error {
|
||||
// options are stored in smartblock pkg because of cyclic dependency :(
|
||||
startTime := time.Now()
|
||||
opts := &smartblock.IndexOptions{}
|
||||
for _, o := range options {
|
||||
o(opts)
|
||||
|
@ -160,7 +158,6 @@ func (i *spaceIndexer) index(ctx context.Context, info smartblock.DocInfo, optio
|
|||
|
||||
details := info.Details
|
||||
|
||||
indexSetTime := time.Now()
|
||||
var hasError bool
|
||||
if indexLinks {
|
||||
if err = i.spaceIndex.UpdateObjectLinks(ctx, info.Id, info.Links); err != nil {
|
||||
|
@ -169,7 +166,6 @@ func (i *spaceIndexer) index(ctx context.Context, info smartblock.DocInfo, optio
|
|||
}
|
||||
}
|
||||
|
||||
indexLinksTime := time.Now()
|
||||
if indexDetails {
|
||||
if err := i.spaceIndex.UpdateObjectDetails(ctx, info.Id, details); err != nil {
|
||||
hasError = true
|
||||
|
@ -199,21 +195,11 @@ func (i *spaceIndexer) index(ctx context.Context, info smartblock.DocInfo, optio
|
|||
} else {
|
||||
_ = i.spaceIndex.DeleteDetails(ctx, []string{info.Id})
|
||||
}
|
||||
indexDetailsTime := time.Now()
|
||||
detailsCount := details.Len()
|
||||
|
||||
if !hasError {
|
||||
saveIndexedHash()
|
||||
}
|
||||
|
||||
metrics.Service.Send(&metrics.IndexEvent{
|
||||
ObjectId: info.Id,
|
||||
IndexLinksTimeMs: indexLinksTime.Sub(indexSetTime).Milliseconds(),
|
||||
IndexDetailsTimeMs: indexDetailsTime.Sub(indexLinksTime).Milliseconds(),
|
||||
IndexSetRelationsTimeMs: indexSetTime.Sub(startTime).Milliseconds(),
|
||||
DetailsCount: detailsCount,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,13 @@ var (
|
|||
bundle.RelationKeyBacklinks,
|
||||
}
|
||||
|
||||
defaultSetFeaturedRelationKeys = []domain.RelationKey{
|
||||
bundle.RelationKeyType,
|
||||
bundle.RelationKeySetOf,
|
||||
bundle.RelationKeyTag,
|
||||
bundle.RelationKeyBacklinks,
|
||||
}
|
||||
|
||||
defaultRecommendedRelationKeys = []domain.RelationKey{
|
||||
bundle.RelationKeyCreatedDate,
|
||||
bundle.RelationKeyCreator,
|
||||
|
@ -36,10 +43,6 @@ var (
|
|||
bundle.RelationKeyLastModifiedBy,
|
||||
bundle.RelationKeyLastOpenedDate,
|
||||
bundle.RelationKeyAddedDate,
|
||||
bundle.RelationKeySource,
|
||||
bundle.RelationKeySourceObject,
|
||||
bundle.RelationKeyImportType,
|
||||
bundle.RelationKeyOrigin,
|
||||
}
|
||||
|
||||
fileSpecificRelationKeysMap = map[domain.RelationKey]struct{}{
|
||||
|
@ -64,10 +67,19 @@ var (
|
|||
errRecommendedRelationsAlreadyFilled = fmt.Errorf("recommended featured relations are already filled")
|
||||
)
|
||||
|
||||
func DefaultFeaturedRelationKeys(typeKey domain.TypeKey) []domain.RelationKey {
|
||||
if typeKey == bundle.TypeKeySet {
|
||||
return defaultSetFeaturedRelationKeys
|
||||
}
|
||||
return defaultFeaturedRelationKeys
|
||||
}
|
||||
|
||||
// FillRecommendedRelations fills recommendedRelations, recommendedFeaturedRelations, recommendedFileRelations
|
||||
// and recommendedHiddenRelations based on object's details.
|
||||
// If these relations are already filled with correct ids, isAlreadyFilled = true is returned
|
||||
func FillRecommendedRelations(ctx context.Context, deriver ObjectIDDeriver, details *domain.Details) (keys []domain.RelationKey, isAlreadyFilled bool, err error) {
|
||||
func FillRecommendedRelations(
|
||||
ctx context.Context, deriver ObjectIDDeriver, details *domain.Details, typeKey domain.TypeKey,
|
||||
) (keys []domain.RelationKey, isAlreadyFilled bool, err error) {
|
||||
keys, err = getRelationKeysFromDetails(details)
|
||||
if err != nil {
|
||||
if errors.Is(err, errRecommendedRelationsAlreadyFilled) {
|
||||
|
@ -95,11 +107,13 @@ func FillRecommendedRelations(ctx context.Context, deriver ObjectIDDeriver, deta
|
|||
keys = other
|
||||
}
|
||||
|
||||
featuredRelationKeys := DefaultFeaturedRelationKeys(typeKey)
|
||||
|
||||
// we should include default system recommended relations and
|
||||
// exclude default recommended featured relations and default hidden relations
|
||||
keys = lo.Uniq(append(keys, defaultRecommendedRelationKeys...))
|
||||
keys = slices.DeleteFunc(keys, func(key domain.RelationKey) bool {
|
||||
return slices.Contains(append(defaultHiddenRelationKeys, defaultFeaturedRelationKeys...), key)
|
||||
return slices.Contains(append(defaultHiddenRelationKeys, featuredRelationKeys...), key)
|
||||
})
|
||||
|
||||
relationIds, err := prepareRelationIds(ctx, deriver, keys)
|
||||
|
@ -108,7 +122,7 @@ func FillRecommendedRelations(ctx context.Context, deriver ObjectIDDeriver, deta
|
|||
}
|
||||
details.SetStringList(bundle.RelationKeyRecommendedRelations, relationIds)
|
||||
|
||||
featuredRelationIds, err := prepareRelationIds(ctx, deriver, defaultFeaturedRelationKeys)
|
||||
featuredRelationIds, err := prepareRelationIds(ctx, deriver, featuredRelationKeys)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("prepare recommended featured relation ids: %w", err)
|
||||
}
|
||||
|
@ -120,7 +134,7 @@ func FillRecommendedRelations(ctx context.Context, deriver ObjectIDDeriver, deta
|
|||
}
|
||||
details.SetStringList(bundle.RelationKeyRecommendedHiddenRelations, hiddenRelationIds)
|
||||
|
||||
return slices.Concat(keys, fileRecommendedRelationKeys, defaultHiddenRelationKeys, defaultFeaturedRelationKeys), false, nil
|
||||
return slices.Concat(keys, fileRecommendedRelationKeys, defaultHiddenRelationKeys, featuredRelationKeys), false, nil
|
||||
}
|
||||
|
||||
func getRelationKeysFromDetails(details *domain.Details) ([]domain.RelationKey, error) {
|
||||
|
|
|
@ -70,7 +70,7 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
})
|
||||
|
||||
// when
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details)
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details, bundle.TypeKeyNote)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
@ -78,7 +78,7 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
assert.Equal(t, tc.expected, details.GetStringList(bundle.RelationKeyRecommendedRelations))
|
||||
assert.Equal(t, defaultRecFeatRelIds, details.GetStringList(bundle.RelationKeyRecommendedFeaturedRelations))
|
||||
assert.Equal(t, defaultRecHiddenRelIds, details.GetStringList(bundle.RelationKeyRecommendedHiddenRelations))
|
||||
assert.Len(t, keys, len(tc.expected)+3+8) // 3 featured and 8 hidden
|
||||
assert.Len(t, keys, len(tc.expected)+3+4) // 3 featured and 4 hidden
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
})
|
||||
|
||||
// when
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details)
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details, bundle.TypeKeyPage)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
@ -130,7 +130,7 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
})
|
||||
|
||||
// when
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details)
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details, bundle.TypeKeyTask)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
@ -138,7 +138,7 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
assert.Equal(t, tc.expected, details.GetStringList(bundle.RelationKeyRecommendedRelations))
|
||||
assert.Equal(t, defaultRecFeatRelIds, details.GetStringList(bundle.RelationKeyRecommendedFeaturedRelations))
|
||||
assert.Equal(t, defaultRecHiddenRelIds, details.GetStringList(bundle.RelationKeyRecommendedHiddenRelations))
|
||||
assert.Len(t, keys, len(tc.expected)+3+8) // 3 featured and 8 hidden
|
||||
assert.Len(t, keys, len(tc.expected)+3+4) // 3 featured and 4 hidden
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,6 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
// given
|
||||
details := domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
bundle.RelationKeyRecommendedRelations: domain.StringList([]string{
|
||||
bundle.RelationKeyOrigin.BundledURL(),
|
||||
bundle.RelationKeyFileExt.BundledURL(),
|
||||
bundle.RelationKeyAddedDate.BundledURL(),
|
||||
bundle.RelationKeyCameraIso.BundledURL(),
|
||||
|
@ -156,7 +155,7 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
})
|
||||
|
||||
// when
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details)
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details, bundle.TypeKeyProject)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
|
@ -169,7 +168,30 @@ func TestFillRecommendedRelations(t *testing.T) {
|
|||
bundle.RelationKeyCameraIso.URL(),
|
||||
bundle.RelationKeyAperture.URL(),
|
||||
}, details.GetStringList(bundle.RelationKeyRecommendedFileRelations))
|
||||
assert.Len(t, keys, 17)
|
||||
assert.Len(t, keys, 13)
|
||||
})
|
||||
|
||||
t.Run("recommendedRelations relations of Set", func(t *testing.T) {
|
||||
// given
|
||||
details := domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{
|
||||
bundle.RelationKeyRecommendedRelations: domain.StringList([]string{
|
||||
bundle.RelationKeySetOf.BundledURL(),
|
||||
bundle.RelationKeyType.BundledURL(),
|
||||
bundle.RelationKeyTag.BundledURL(),
|
||||
bundle.RelationKeyCreatedDate.BundledURL(),
|
||||
}),
|
||||
})
|
||||
|
||||
// when
|
||||
keys, isAlreadyFilled, err := FillRecommendedRelations(nil, &mockDeriver{}, details, bundle.TypeKeySet)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isAlreadyFilled)
|
||||
assert.Equal(t, buildRelationIds(defaultRecommendedRelationKeys), details.GetStringList(bundle.RelationKeyRecommendedRelations))
|
||||
assert.Equal(t, buildRelationIds(defaultSetFeaturedRelationKeys), details.GetStringList(bundle.RelationKeyRecommendedFeaturedRelations))
|
||||
assert.Equal(t, defaultRecHiddenRelIds, details.GetStringList(bundle.RelationKeyRecommendedHiddenRelations))
|
||||
assert.Len(t, keys, 4+3+4) // 4 featured + 3 sidebar + 4 hidden
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ const CName = "subscription"
|
|||
|
||||
var log = logging.Logger("anytype-mw-subscription")
|
||||
|
||||
var batchTime = 50 * time.Millisecond
|
||||
var batchTime = 250 * time.Millisecond
|
||||
|
||||
func New() Service {
|
||||
return &service{}
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestSyncSubscriptions(t *testing.T) {
|
|||
subs.(*syncSubscriptions).service = testSubs
|
||||
err := subs.Run(context.Background())
|
||||
require.NoError(t, err)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
spaceSub, err := subs.GetSubscription("spaceId")
|
||||
require.NoError(t, err)
|
||||
syncCnt := spaceSub.SyncingObjectsCount([]string{"1", "2"})
|
||||
|
@ -59,7 +59,7 @@ func TestSyncSubscriptions(t *testing.T) {
|
|||
objects[i][bundle.RelationKeySyncStatus] = domain.Int64(int64(domain.ObjectSyncStatusSynced))
|
||||
testSubs.AddObjects(t, "spaceId", []objectstore.TestObject{objects[i]})
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
syncCnt = spaceSub.SyncingObjectsCount([]string{"1", "2"})
|
||||
require.Equal(t, 2, syncCnt)
|
||||
err = subs.Close(context.Background())
|
||||
|
|
|
@ -73,6 +73,51 @@ func (_c *MockWallet_Account_Call) RunAndReturn(run func() *accountdata.AccountK
|
|||
return _c
|
||||
}
|
||||
|
||||
// FtsPrimaryLang provides a mock function with given fields:
|
||||
func (_m *MockWallet) FtsPrimaryLang() string {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for FtsPrimaryLang")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockWallet_FtsPrimaryLang_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FtsPrimaryLang'
|
||||
type MockWallet_FtsPrimaryLang_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// FtsPrimaryLang is a helper method to define mock.On call
|
||||
func (_e *MockWallet_Expecter) FtsPrimaryLang() *MockWallet_FtsPrimaryLang_Call {
|
||||
return &MockWallet_FtsPrimaryLang_Call{Call: _e.mock.On("FtsPrimaryLang")}
|
||||
}
|
||||
|
||||
func (_c *MockWallet_FtsPrimaryLang_Call) Run(run func()) *MockWallet_FtsPrimaryLang_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockWallet_FtsPrimaryLang_Call) Return(_a0 string) *MockWallet_FtsPrimaryLang_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockWallet_FtsPrimaryLang_Call) RunAndReturn(run func() string) *MockWallet_FtsPrimaryLang_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetAccountEthAddress provides a mock function with given fields:
|
||||
func (_m *MockWallet) GetAccountEthAddress() wallet.EthAddress {
|
||||
ret := _m.Called()
|
||||
|
|
|
@ -29,6 +29,7 @@ type EthAddress = common.Address
|
|||
type wallet struct {
|
||||
rootPath string
|
||||
repoPath string // other components will init their files/dirs inside
|
||||
lang string
|
||||
deviceKeyPath string
|
||||
|
||||
accountKey crypto.PrivKey
|
||||
|
@ -117,6 +118,10 @@ func (r *wallet) RepoPath() string {
|
|||
return r.repoPath
|
||||
}
|
||||
|
||||
func (r *wallet) FtsPrimaryLang() string {
|
||||
return r.lang
|
||||
}
|
||||
|
||||
func (r *wallet) RootPath() string {
|
||||
return r.rootPath
|
||||
}
|
||||
|
@ -129,12 +134,13 @@ func (r *wallet) Account() *accountdata.AccountKeys {
|
|||
return r.accountData
|
||||
}
|
||||
|
||||
func NewWithAccountRepo(rootPath string, derivationResult crypto.DerivationResult) Wallet {
|
||||
func NewWithAccountRepo(rootPath string, derivationResult crypto.DerivationResult, lang string) Wallet {
|
||||
accountId := derivationResult.Identity.GetPublic().Account()
|
||||
repoPath := filepath.Join(rootPath, accountId)
|
||||
return &wallet{
|
||||
rootPath: rootPath,
|
||||
repoPath: repoPath,
|
||||
lang: lang,
|
||||
masterKey: derivationResult.MasterKey,
|
||||
oldAccountKey: derivationResult.OldAccountKey,
|
||||
accountKey: derivationResult.Identity,
|
||||
|
@ -160,6 +166,7 @@ func NewWithRepoPathAndKeys(repoPath string, accountKeypair, deviceKeypair crypt
|
|||
type Wallet interface {
|
||||
RootPath() string
|
||||
RepoPath() string
|
||||
FtsPrimaryLang() string
|
||||
GetAccountPrivkey() crypto.PrivKey
|
||||
GetDevicePrivkey() crypto.PrivKey
|
||||
GetOldAccountKey() crypto.PrivKey
|
||||
|
|
|
@ -13,8 +13,11 @@ make download-tantivy-all-force
|
|||
|
||||
#### Mac
|
||||
As of 16.01.23 last protobuf version (21.12) broke the JS plugin support, so you can use the v3 branch:
|
||||
Make sure you've removed protobuf
|
||||
```
|
||||
brew remove protobuf --ignore-dependencies
|
||||
brew install protobuf@3
|
||||
brew link --force --overwrite protobuf@3
|
||||
```
|
||||
|
||||
To generate Swift protobuf:
|
||||
|
|
|
@ -3510,6 +3510,7 @@ TODO: Remove this request if we do not need it, GO-1926
|
|||
| ----- | ---- | ----- | ----------- |
|
||||
| id | [string](#string) | | Id of a selected account |
|
||||
| rootPath | [string](#string) | | |
|
||||
| fulltextPrimaryLanguage | [string](#string) | | optional, default fts language |
|
||||
|
||||
|
||||
|
||||
|
@ -3732,6 +3733,7 @@ Middleware-to-front-end response to an account recover request, that can contain
|
|||
| path | [string](#string) | | |
|
||||
| rootPath | [string](#string) | | |
|
||||
| icon | [int64](#int64) | | |
|
||||
| fulltextPrimaryLanguage | [string](#string) | | optional, default fts language |
|
||||
|
||||
|
||||
|
||||
|
@ -3849,6 +3851,7 @@ User can select an account from those, that came with an AccountAdd events
|
|||
| networkCustomConfigFilePath | [string](#string) | | config path for the custom network mode |
|
||||
| preferYamuxTransport | [bool](#bool) | | optional, default is false, recommended in case of problems with QUIC transport |
|
||||
| jsonApiListenAddr | [string](#string) | | optional, if empty json api will not be started; 127.0.0.1:31009 should be the default one |
|
||||
| fulltextPrimaryLanguage | [string](#string) | | optional, default fts language |
|
||||
|
||||
|
||||
|
||||
|
@ -20297,6 +20300,7 @@ Front-end-to-middleware request to create a new wallet
|
|||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| rootPath | [string](#string) | | Path to a wallet directory |
|
||||
| fulltextPrimaryLanguage | [string](#string) | | optional, default fts language |
|
||||
|
||||
|
||||
|
||||
|
@ -20415,6 +20419,7 @@ Front end to middleware request-to-recover-a wallet with this mnemonic and a roo
|
|||
| ----- | ---- | ----- | ----------- |
|
||||
| rootPath | [string](#string) | | Path to a wallet directory |
|
||||
| mnemonic | [string](#string) | | Mnemonic of a wallet to recover |
|
||||
| fulltextPrimaryLanguage | [string](#string) | | optional, default fts language |
|
||||
|
||||
|
||||
|
||||
|
@ -29004,6 +29009,7 @@ Contains basic information about a user account
|
|||
| timeZone | [string](#string) | | time zone from config |
|
||||
| analyticsId | [string](#string) | | |
|
||||
| networkId | [string](#string) | | network id to which anytype is connected |
|
||||
| ethereumAddress | [string](#string) | | we have Any PK AND Ethereum PK derived from one seed phrase |
|
||||
|
||||
|
||||
|
||||
|
|
94
go.mod
94
go.mod
|
@ -7,17 +7,17 @@ require (
|
|||
github.com/PuerkitoBio/goquery v1.10.2
|
||||
github.com/VividCortex/ewma v1.2.0
|
||||
github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
|
||||
github.com/anyproto/any-store v0.1.7
|
||||
github.com/anyproto/any-sync v0.6.0
|
||||
github.com/anyproto/any-store v0.1.8
|
||||
github.com/anyproto/any-sync v0.6.1
|
||||
github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250131145601-de288583ff2a
|
||||
github.com/anyproto/go-chash v0.1.0
|
||||
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438
|
||||
github.com/anyproto/go-slip10 v1.0.0
|
||||
github.com/anyproto/lexid v0.0.4
|
||||
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5
|
||||
github.com/anyproto/tantivy-go v0.3.1
|
||||
github.com/anyproto/tantivy-go v1.0.1
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
|
||||
github.com/avast/retry-go/v4 v4.6.0
|
||||
github.com/avast/retry-go/v4 v4.6.1
|
||||
github.com/chai2010/webp v1.1.2-0.20240612091223-aa1b379218b7
|
||||
github.com/cheggaaa/mb/v3 v3.0.2
|
||||
github.com/dave/jennifer v1.7.1
|
||||
|
@ -29,6 +29,7 @@ require (
|
|||
github.com/dsoprea/go-exif/v3 v3.0.1
|
||||
github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102
|
||||
github.com/ethereum/go-ethereum v1.13.15
|
||||
github.com/gabriel-vasile/mimetype v1.4.8
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
|
||||
github.com/go-chi/chi/v5 v5.2.1
|
||||
|
@ -45,17 +46,17 @@ require (
|
|||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/yamux v0.1.2
|
||||
github.com/hbagdi/go-unsplash v0.0.0-20230414214043-474fc02c9119
|
||||
github.com/huandu/skiplist v1.2.1
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/improbable-eng/grpc-web v0.15.0
|
||||
github.com/ipfs/boxo v0.27.4
|
||||
github.com/ipfs/boxo v0.29.0
|
||||
github.com/ipfs/go-block-format v0.2.0
|
||||
github.com/ipfs/go-cid v0.5.0
|
||||
github.com/ipfs/go-datastore v0.7.0
|
||||
github.com/ipfs/go-ds-flatfs v0.5.1
|
||||
github.com/ipfs/go-datastore v0.8.2
|
||||
github.com/ipfs/go-ds-flatfs v0.5.5
|
||||
github.com/ipfs/go-ipld-format v0.6.0
|
||||
github.com/ipfs/go-log v1.0.5
|
||||
github.com/joho/godotenv v1.5.1
|
||||
|
@ -81,7 +82,7 @@ require (
|
|||
github.com/otiai10/copy v1.14.1
|
||||
github.com/otiai10/opengraph/v2 v2.1.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.21.0
|
||||
github.com/prometheus/client_golang v1.21.1
|
||||
github.com/pseudomuto/protoc-gen-doc v1.5.1
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
|
||||
github.com/samber/lo v1.49.1
|
||||
|
@ -92,7 +93,7 @@ require (
|
|||
github.com/stretchr/testify v1.10.0
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/swaggo/swag v1.16.4
|
||||
github.com/swaggo/swag/v2 v2.0.0-rc4
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||
github.com/valyala/fastjson v1.6.4
|
||||
github.com/vektra/mockery/v2 v2.47.0
|
||||
|
@ -103,14 +104,14 @@ require (
|
|||
go.uber.org/mock v0.5.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
|
||||
golang.org/x/image v0.24.0
|
||||
golang.org/x/mobile v0.0.0-20241108191957-fa514ef75a0f
|
||||
golang.org/x/net v0.35.0
|
||||
golang.org/x/oauth2 v0.26.0
|
||||
golang.org/x/sys v0.30.0
|
||||
golang.org/x/text v0.22.0
|
||||
google.golang.org/grpc v1.70.0
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa
|
||||
golang.org/x/image v0.25.0
|
||||
golang.org/x/mobile v0.0.0-20250218173827-cd096645fcd3
|
||||
golang.org/x/net v0.37.0
|
||||
golang.org/x/oauth2 v0.28.0
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/text v0.23.0
|
||||
google.golang.org/grpc v1.71.0
|
||||
gopkg.in/Graylog2/go-gelf.v2 v2.0.0-20180125164251-1832d8546a9f
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
@ -125,8 +126,6 @@ require (
|
|||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
||||
|
@ -148,7 +147,7 @@ require (
|
|||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
|
||||
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
|
@ -157,11 +156,10 @@ require (
|
|||
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c // indirect
|
||||
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/flopp/go-findfont v0.1.0 // indirect
|
||||
github.com/fogleman/gg v1.3.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/gammazero/deque v1.0.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
|
@ -189,7 +187,7 @@ require (
|
|||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/flatbuffers v1.12.1 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/gosimple/unidecode v1.0.1 // indirect
|
||||
|
@ -198,7 +196,6 @@ require (
|
|||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/holiman/uint256 v1.2.4 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/ipfs/bbloom v0.0.4 // indirect
|
||||
|
@ -206,23 +203,22 @@ require (
|
|||
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
|
||||
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
|
||||
github.com/ipfs/go-metrics-interface v0.3.0 // indirect
|
||||
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
|
||||
github.com/ipld/go-ipld-prime v0.21.0 // indirect
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
|
||||
github.com/jbenet/goprocess v0.1.4 // indirect
|
||||
github.com/jinzhu/copier v0.3.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/libp2p/go-libp2p v0.38.2 // indirect
|
||||
github.com/libp2p/go-libp2p v0.41.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.62 // indirect
|
||||
github.com/miekg/dns v1.1.63 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
|
@ -231,7 +227,7 @@ require (
|
|||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||
github.com/multiformats/go-multiaddr v0.14.0 // indirect
|
||||
github.com/multiformats/go-multiaddr v0.15.0 // indirect
|
||||
github.com/multiformats/go-multicodec v0.9.0 // indirect
|
||||
github.com/multiformats/go-multistream v0.6.0 // indirect
|
||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||
|
@ -249,9 +245,8 @@ require (
|
|||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/pseudomuto/protokit v0.2.1 // indirect
|
||||
github.com/quic-go/quic-go v0.49.0 // indirect
|
||||
github.com/quic-go/quic-go v0.50.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rs/cors v1.11.0 // indirect
|
||||
github.com/rs/zerolog v1.29.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
|
@ -265,7 +260,7 @@ require (
|
|||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/sv-tools/openapi v0.2.1 // indirect
|
||||
github.com/swaggo/swag/v2 v2.0.0-rc4 // indirect
|
||||
github.com/swaggo/swag v1.16.4 // indirect
|
||||
github.com/tetratelabs/wazero v1.8.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
|
@ -279,26 +274,27 @@ require (
|
|||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zeebo/errs v1.4.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/mod v0.23.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/term v0.30.0 // indirect
|
||||
golang.org/x/time v0.10.0 // indirect
|
||||
golang.org/x/tools v0.29.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
|
||||
google.golang.org/protobuf v1.36.2 // indirect
|
||||
golang.org/x/tools v0.30.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
lukechampine.com/blake3 v1.4.0 // indirect
|
||||
modernc.org/libc v1.61.13 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.8.2 // indirect
|
||||
modernc.org/sqlite v1.34.5 // indirect
|
||||
modernc.org/sqlite v1.36.0 // indirect
|
||||
nhooyr.io/websocket v1.8.7 // indirect
|
||||
)
|
||||
|
||||
|
@ -316,7 +312,7 @@ replace gopkg.in/Graylog2/go-gelf.v2 => github.com/anyproto/go-gelf v0.0.0-20210
|
|||
|
||||
replace github.com/araddon/dateparse => github.com/mehanizm/dateparse v0.0.0-20210806203422-f82c8742c9f8 // use a fork to support dd.mm.yyyy date format
|
||||
|
||||
replace github.com/multiformats/go-multiaddr => github.com/anyproto/go-multiaddr v0.8.1-0.20221213144344-0b6b93adaec4
|
||||
replace github.com/multiformats/go-multiaddr => github.com/anyproto/go-multiaddr v0.8.1-0.20250307125826-51ba58e2ebc7
|
||||
|
||||
replace github.com/gogo/protobuf => github.com/anyproto/protobuf v1.3.3-0.20240201225420-6e325cf0ac38
|
||||
|
||||
|
@ -325,3 +321,5 @@ replace google.golang.org/genproto/googleapis/rpc => google.golang.org/genproto/
|
|||
replace github.com/btcsuite/btcutil => github.com/btcsuite/btcd/btcutil v1.1.5
|
||||
|
||||
replace github.com/dsoprea/go-jpeg-image-structure/v2 => github.com/dchesterton/go-jpeg-image-structure/v2 v2.0.0-20240318203529-c3eea088bd38
|
||||
|
||||
replace zombiezen.com/go/sqlite => github.com/anyproto/go-sqlite v0.0.0-20250226111550-9b81a8e3cff4
|
||||
|
|
256
go.sum
256
go.sum
|
@ -56,10 +56,6 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
|
|||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||
github.com/PuerkitoBio/goquery v1.10.2 h1:7fh2BdHcG6VFZsK7toXBT/Bh1z5Wmy8Q9MV9HqT2AM8=
|
||||
github.com/PuerkitoBio/goquery v1.10.2/go.mod h1:0guWGjcLu9AYC7C1GHnpysHy056u9aEkUHwhdnePMCU=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
|
@ -82,10 +78,10 @@ github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h
|
|||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
|
||||
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
|
||||
github.com/anyproto/any-store v0.1.7 h1:E3DntI+JXo3h7v0WTUJWH+nm7G4MV0PNOXZ6SFzQ2OU=
|
||||
github.com/anyproto/any-store v0.1.7/go.mod h1:nbyRoJYOlvSWU1xDOrmgPP96UeoTf4eYZ9k+qqLK9k8=
|
||||
github.com/anyproto/any-sync v0.6.0 h1:JDxOTUuzGCHaeyid64tVIahYySCuonOK8Gwpf8s8lJ0=
|
||||
github.com/anyproto/any-sync v0.6.0/go.mod h1:GrVtVp1VWqWRyYErJVsJVUhb6yzcvelQ+HWOXZ4f0tc=
|
||||
github.com/anyproto/any-store v0.1.8 h1:/bxUVq6sBTwYkmPL2g1xUAWNb3axF+zPhP2dvdEBH68=
|
||||
github.com/anyproto/any-store v0.1.8/go.mod h1:GpnVhcGm5aUQtOwCnKeTt4jsWgVXZ773WbQVLFdeCFo=
|
||||
github.com/anyproto/any-sync v0.6.1 h1:Dasbp7qGQme8diGGpzaDQfSDs5o7PAK3E5rxHHrB/+4=
|
||||
github.com/anyproto/any-sync v0.6.1/go.mod h1:5js8TNBdqe75zwlr9XEQSVDtwhsvEU2qLeC2wTnT/Fo=
|
||||
github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250131145601-de288583ff2a h1:ZZM+0OUCQMWSLSflpkf0ZMVo3V76qEDDIXPpQOClNs0=
|
||||
github.com/anyproto/anytype-publish-server/publishclient v0.0.0-20250131145601-de288583ff2a/go.mod h1:4fkueCZcGniSMXkrwESO8zzERrh/L7WHimRNWecfGM0=
|
||||
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc=
|
||||
|
@ -96,14 +92,16 @@ github.com/anyproto/go-gelf v0.0.0-20210418191311-774bd5b016e7 h1:SyEu5uxZ5nKHEJ
|
|||
github.com/anyproto/go-gelf v0.0.0-20210418191311-774bd5b016e7/go.mod h1:N7kTiXo+LLnV94mHMr7Veos3I1SZ/ELcbkG8sZvcAPI=
|
||||
github.com/anyproto/go-log/v2 v2.1.2-0.20220721095711-bcf09ff293b2 h1:X8xiwPlNiSQs1HKguhZyHYs4XFQLWsj566bFsRjN7hM=
|
||||
github.com/anyproto/go-log/v2 v2.1.2-0.20220721095711-bcf09ff293b2/go.mod h1:TMD+iYDL/QBjspKUN0Ypxpr2IMAz3uGUAsbCeClDQ+4=
|
||||
github.com/anyproto/go-multiaddr v0.8.1-0.20221213144344-0b6b93adaec4 h1:ZUvfKh0DCmmY1wjMtBPS3ggvCvQA0+spKFsAuSSeCsU=
|
||||
github.com/anyproto/go-multiaddr v0.8.1-0.20221213144344-0b6b93adaec4/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs=
|
||||
github.com/anyproto/go-multiaddr v0.8.1-0.20250307125826-51ba58e2ebc7 h1:SD0mX7Ds438ZP6J1g7qpXN4naRi/Naa0umTvlTba76c=
|
||||
github.com/anyproto/go-multiaddr v0.8.1-0.20250307125826-51ba58e2ebc7/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
||||
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438 h1:flfZXdcXB2iVHrTZDwSMlJ7RCRS/ydiPw63xWr+waSU=
|
||||
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438/go.mod h1:cmdcU4pcVTftMlM89z+d8dLBJc02HtY5tI12yQucUxM=
|
||||
github.com/anyproto/go-slip10 v1.0.0 h1:uAEtSuudR3jJBOfkOXf3bErxVoxbuKwdoJN55M1i6IA=
|
||||
github.com/anyproto/go-slip10 v1.0.0/go.mod h1:BCmIlM1KB8wX6K4/8pOvxPl9oVKfEvZ5vsmO5rkK6vg=
|
||||
github.com/anyproto/go-slip21 v1.0.0 h1:CI7lUqTIwmPOEGVAj4jyNLoICvueh++0U2HoAi3m2ZY=
|
||||
github.com/anyproto/go-slip21 v1.0.0/go.mod h1:gbIJt7HAdr5DuT4f2pFTKCBSUWYsm/fysHBNqgsuxT0=
|
||||
github.com/anyproto/go-sqlite v0.0.0-20250226111550-9b81a8e3cff4 h1:HzVjm45VOUVFUrxh2s0cRR4lqfCr/VAee6wNzPLcApI=
|
||||
github.com/anyproto/go-sqlite v0.0.0-20250226111550-9b81a8e3cff4/go.mod h1:0w9F1DN9IZj9AcLS9YDKMboubCACkwYCGkzoy3eG5ik=
|
||||
github.com/anyproto/html-to-markdown v0.0.0-20231025221133-830bf0a6f139 h1:Wp9z0Q2kAstznWUmTZyOb9UgpVmUgYt1LXRvK/cg10E=
|
||||
github.com/anyproto/html-to-markdown v0.0.0-20231025221133-830bf0a6f139/go.mod h1:1zaDDQVWTRwNksmTUTkcVXqgNF28YHiEUIm8FL9Z+II=
|
||||
github.com/anyproto/lexid v0.0.4 h1:2ztI0y5pNdtojd3vChw/YV/P6IO9pB7PccYysImDxWI=
|
||||
|
@ -114,8 +112,8 @@ github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5 h1:aY7tBzQ+z8H
|
|||
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5/go.mod h1:5+PHE01DgsDPkralb8MYmGg2sPQahsqEJ9ue7ciDHKg=
|
||||
github.com/anyproto/ristretto v0.1.2-0.20240221153107-2b23839cc50c h1:GicoaTUyB2mtCIl3YMrO0OzysqRT5GA4vuvDsqEkhSM=
|
||||
github.com/anyproto/ristretto v0.1.2-0.20240221153107-2b23839cc50c/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
|
||||
github.com/anyproto/tantivy-go v0.3.1 h1:59XePWnHlaTOgw1jVqpKD7oyZa8nwY5+U9UKnt0HHZU=
|
||||
github.com/anyproto/tantivy-go v0.3.1/go.mod h1:7hhkPpyTq7+W1dx9Dcva4bsg4TLHq9xqmmYLCwqDq/k=
|
||||
github.com/anyproto/tantivy-go v1.0.1 h1:Uc9WqwGEDsVUEwRgSg4nmhoW20GjMUBKRz5FYw4r+ns=
|
||||
github.com/anyproto/tantivy-go v1.0.1/go.mod h1:LtipOpRjGtcYMGcop6gQN7rVl1Pc6BlIs9BTMqeWMsk=
|
||||
github.com/anyproto/zeroconf/v2 v2.2.1-0.20240228113933-f90a5cc4439d h1:5bj7nX/AS8sxGpTIrapE7PC4oPlhkHMwMqXlJbUHBlg=
|
||||
github.com/anyproto/zeroconf/v2 v2.2.1-0.20240228113933-f90a5cc4439d/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
|
@ -124,8 +122,8 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
|
|||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA=
|
||||
github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE=
|
||||
github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk=
|
||||
github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
|
@ -227,11 +225,11 @@ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6Uh
|
|||
github.com/dchesterton/go-jpeg-image-structure/v2 v2.0.0-20240318203529-c3eea088bd38 h1:GDvo0S+xL3iMJYofhBVQVM6EuAcTCoEV1096iN1pedI=
|
||||
github.com/dchesterton/go-jpeg-image-structure/v2 v2.0.0-20240318203529-c3eea088bd38/go.mod h1:WaARaUjQuSuDCDFAiU/GwzfxMTJBulfEhqEA2Tx6B4Y=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
|
||||
|
@ -283,8 +281,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
|
||||
github.com/ethereum/go-ethereum v1.13.15 h1:U7sSGYGo4SPjP6iNIifNoyIAiNjrmQkz6EwQG+/EZWo=
|
||||
github.com/ethereum/go-ethereum v1.13.15/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
|
@ -307,8 +305,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
|||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gammazero/chanqueue v1.0.0 h1:FER/sMailGFA3DDvFooEkipAMU+3c9Bg3bheloPSz6o=
|
||||
github.com/gammazero/chanqueue v1.0.0/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
|
||||
github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34=
|
||||
|
@ -349,21 +347,15 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
|
|||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
|
@ -492,11 +484,10 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
|||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
|
||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
@ -531,8 +522,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
|||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
|
||||
github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
|
||||
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
@ -591,21 +580,20 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
|
|||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
|
||||
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
|
||||
github.com/ipfs/boxo v0.27.4 h1:6nC8lY5GnR6whAbW88hFz6L13wZUj2vr5BRe3iTvYBI=
|
||||
github.com/ipfs/boxo v0.27.4/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
|
||||
github.com/ipfs/boxo v0.29.0 h1:clzd7PglUcE+Ufq1KucS3aKID7pzGVaSgcdRsW395t4=
|
||||
github.com/ipfs/boxo v0.29.0/go.mod h1:c3R52nMlgMsN1tADffYcogKoVRsX1RJE1TMYSpJ4uVs=
|
||||
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
|
||||
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
|
||||
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
|
||||
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
|
||||
github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
|
||||
github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
|
||||
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
|
||||
github.com/ipfs/go-datastore v0.7.0 h1:a6JMuRFKYhw6XXmIVoTthF8ZFm4QQXvLDXFhXRVv8Go=
|
||||
github.com/ipfs/go-datastore v0.7.0/go.mod h1:ucOWMfbOPI6ZEyaIB1q/+78RPLBPERfuUVYX1EPnNpQ=
|
||||
github.com/ipfs/go-datastore v0.8.2 h1:Jy3wjqQR6sg/LhyY0NIePZC3Vux19nLtg7dx0TVqr6U=
|
||||
github.com/ipfs/go-datastore v0.8.2/go.mod h1:W+pI1NsUsz3tcsAACMtfC+IZdnQTnC/7VfPoJBQuts0=
|
||||
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
|
||||
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
|
||||
github.com/ipfs/go-ds-flatfs v0.5.1 h1:ZCIO/kQOS/PSh3vcF1H6a8fkRGS7pOfwfPdx4n/KJH4=
|
||||
github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||
github.com/ipfs/go-ds-flatfs v0.5.5 h1:lkx5C99pFBMI7T1sYF7y3v7xIYekNVNMp/95Gm9Y3tY=
|
||||
github.com/ipfs/go-ds-flatfs v0.5.5/go.mod h1:bM7+m7KFUyv5dp3RBKTr3+OHgZ6h8ydCQkO7tjeO9Z4=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||
github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
|
||||
|
@ -616,15 +604,14 @@ github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten
|
|||
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
|
||||
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
|
||||
github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM=
|
||||
github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A=
|
||||
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
|
||||
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
|
||||
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
|
||||
github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
|
||||
github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
|
||||
github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
|
||||
github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
|
||||
github.com/ipfs/go-test v0.0.4 h1:DKT66T6GBB6PsDFLoO56QZPrOmzJkqU1FZH5C9ySkew=
|
||||
github.com/ipfs/go-test v0.0.4/go.mod h1:qhIM1EluEfElKKM6fnWxGn822/z9knUGM1+I/OAQNKI=
|
||||
github.com/ipfs/go-test v0.2.1 h1:/D/a8xZ2JzkYqcVcV/7HYlCnc7bv/pKHQiX5TdClkPE=
|
||||
github.com/ipfs/go-test v0.2.1/go.mod h1:dzu+KB9cmWjuJnXFDYJwC25T3j1GcN57byN+ixmK39M=
|
||||
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
|
||||
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
|
||||
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
|
||||
|
@ -633,11 +620,8 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd
|
|||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA=
|
||||
github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
|
||||
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
|
||||
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
|
@ -677,19 +661,18 @@ github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
|||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
|
||||
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
|
||||
github.com/koron/go-ssdp v0.0.5 h1:E1iSMxIs4WqxTbIBLtmNBeOOC+1sCIXQeqTWVnpmwhk=
|
||||
github.com/koron/go-ssdp v0.0.5/go.mod h1:Qm59B7hpKpDqfyRNWRNr00jGwLdXjDyZh6y7rH6VS0w=
|
||||
github.com/kovidgoyal/imaging v1.6.4 h1:K0idhRPXnRrJBKnBYcTfI1HTWSNDeAn7hYDvf9I0dCk=
|
||||
github.com/kovidgoyal/imaging v1.6.4/go.mod h1:bEIgsaZmXlvFfkv/CUxr9rJook6AQkJnpB5EPosRfRY=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
|
@ -706,22 +689,20 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6
|
|||
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||
github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw=
|
||||
github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc=
|
||||
github.com/libp2p/go-libp2p v0.38.2 h1:9SZQDOCi82A25An4kx30lEtr6kGTxrtoaDkbs5xrK5k=
|
||||
github.com/libp2p/go-libp2p v0.38.2/go.mod h1:QWV4zGL3O9nXKdHirIC59DoRcZ446dfkjbOJ55NEWFo=
|
||||
github.com/libp2p/go-libp2p v0.41.0 h1:JRaD39dqf/tBBGapJ0T38N73vOaDCsWgcx3mE6HgXWk=
|
||||
github.com/libp2p/go-libp2p v0.41.0/go.mod h1:Be8QYqC4JW6Xq8buukNeoZJjyT1XUDcGoIooCHm1ye4=
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
|
||||
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
|
||||
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
|
||||
github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
|
||||
github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
|
||||
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
|
||||
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
|
||||
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
|
||||
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
|
||||
github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
|
||||
github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
|
||||
github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8=
|
||||
github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE=
|
||||
github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
|
||||
github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
|
||||
github.com/libp2p/go-yamux/v5 v5.0.0 h1:2djUh96d3Jiac/JpGkKs4TO49YhsfLopAoryfPmf+Po=
|
||||
github.com/libp2p/go-yamux/v5 v5.0.0/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
|
@ -733,7 +714,6 @@ github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a
|
|||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
|
@ -763,8 +743,8 @@ github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwX
|
|||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/miolini/datacounter v1.0.3 h1:tanOZPVblGXQl7/bSZWoEM8l4KK83q24qwQLMrO/HOA=
|
||||
|
@ -886,36 +866,40 @@ github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk
|
|||
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
||||
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
|
||||
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
|
||||
github.com/pion/ice/v2 v2.3.37 h1:ObIdaNDu1rCo7hObhs34YSBcO7fjslJMZV0ux+uZWh0=
|
||||
github.com/pion/ice/v2 v2.3.37/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ=
|
||||
github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
|
||||
github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
|
||||
github.com/pion/ice/v4 v4.0.6 h1:jmM9HwI9lfetQV/39uD0nY4y++XZNPhvzIPCb8EwxUM=
|
||||
github.com/pion/ice/v4 v4.0.6/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
|
||||
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8=
|
||||
github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk=
|
||||
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
|
||||
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||
github.com/pion/rtp v1.8.10 h1:puphjdbjPB+L+NFaVuZ5h6bt1g5q4kFIoI+r5q/g0CU=
|
||||
github.com/pion/rtp v1.8.10/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
||||
github.com/pion/sctp v1.8.35 h1:qwtKvNK1Wc5tHMIYgTDJhfZk7vATGVHhXbUDfHbYwzA=
|
||||
github.com/pion/sctp v1.8.35/go.mod h1:EcXP8zCYVTRy3W9xtOF7wJm1L1aXfKRQzaM33SjQlzg=
|
||||
github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY=
|
||||
github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M=
|
||||
github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk=
|
||||
github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
|
||||
github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
|
||||
github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
||||
github.com/pion/sctp v1.8.36 h1:owNudmnz1xmhfYje5L/FCav3V9wpPRePHle3Zi+P+M0=
|
||||
github.com/pion/sctp v1.8.36/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
|
||||
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
|
||||
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
|
||||
github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
|
||||
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
|
||||
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
|
||||
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
|
||||
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
|
||||
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
|
||||
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
|
||||
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
|
||||
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
||||
github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
|
||||
github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
|
||||
github.com/pion/webrtc/v3 v3.3.5 h1:ZsSzaMz/i9nblPdiAkZoP+E6Kmjw+jnyq3bEmU3EtRg=
|
||||
github.com/pion/webrtc/v3 v3.3.5/go.mod h1:liNa+E1iwyzyXqNUwvoMRNQ10x8h8FOeJKL8RkIbamE=
|
||||
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
|
||||
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
|
||||
github.com/pion/webrtc/v4 v4.0.10 h1:Hq/JLjhqLxi+NmCtE8lnRPDr8H4LcNvwg8OxVcdv56Q=
|
||||
github.com/pion/webrtc/v4 v4.0.10/go.mod h1:ViHLVaNpiuvaH8pdiuQxuA9awuE6KVzAXx3vVWilOck=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
@ -934,8 +918,8 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
|
|||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA=
|
||||
github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
|
@ -965,8 +949,8 @@ github.com/pseudomuto/protokit v0.2.1 h1:kCYpE3thoR6Esm0CUvd5xbrDTOZPvQPTDeyXpZf
|
|||
github.com/pseudomuto/protokit v0.2.1/go.mod h1:gt7N5Rz2flBzYafvaxyIxMZC0TTF5jDZfRnw25hAAyo=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
|
||||
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
|
||||
github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo=
|
||||
github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
|
||||
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
|
@ -975,8 +959,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
|
|||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
|
||||
github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
|
@ -1150,16 +1134,18 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
|
@ -1207,8 +1193,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
|||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -1223,14 +1209,14 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
||||
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
@ -1244,8 +1230,8 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
|
|||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20241108191957-fa514ef75a0f h1:23H/YlmTHfmmvpZ+ajKZL0qLz0+IwFOIqQA0mQbmLeM=
|
||||
golang.org/x/mobile v0.0.0-20241108191957-fa514ef75a0f/go.mod h1:UbSUP4uu/C9hw9R2CkojhXlAxvayHjBdU9aRvE+c1To=
|
||||
golang.org/x/mobile v0.0.0-20250218173827-cd096645fcd3 h1:0V/7Y1FEaFdAzb9DkVDh4QFp4vL4yYCiJ5cjk80lZyA=
|
||||
golang.org/x/mobile v0.0.0-20250218173827-cd096645fcd3/go.mod h1:j5VYNgQ6lZYZlzHFjdgS2UeqRSZunDk+/zXVTAIA3z4=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
|
@ -1260,8 +1246,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -1309,7 +1295,6 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
@ -1324,8 +1309,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -1335,8 +1320,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
|
||||
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -1354,8 +1339,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -1415,7 +1400,6 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -1441,8 +1425,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -1453,8 +1437,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -1470,8 +1454,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -1540,8 +1524,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -1618,8 +1602,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D
|
|||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a h1:OAiGFfOiA0v9MRYsSidp3ubZaBnteRUyn3xB2ZQ5G/E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
|
@ -1645,8 +1629,8 @@ google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
|||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -1657,8 +1641,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -1700,8 +1684,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w=
|
||||
lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0=
|
||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
||||
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
|
||||
|
@ -1720,8 +1704,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
|||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g=
|
||||
modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE=
|
||||
modernc.org/sqlite v1.36.0 h1:EQXNRn4nIS+gfsKeUTymHIz1waxuv5BzU7558dHSfH8=
|
||||
modernc.org/sqlite v1.36.0/go.mod h1:7MPwH7Z6bREicF9ZVUR78P1IKuxfZ8mRIDHD0iD+8TU=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
|
@ -1738,5 +1722,3 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
|||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
storj.io/drpc v0.0.34 h1:q9zlQKfJ5A7x8NQNFk8x7eKUF78FMhmAbZLnFK+og7I=
|
||||
storj.io/drpc v0.0.34/go.mod h1:Y9LZaa8esL1PW2IDMqJE7CFSNq7d5bQ3RI7mGPtmKMg=
|
||||
zombiezen.com/go/sqlite v1.4.0 h1:N1s3RIljwtp4541Y8rM880qgGIgq3fTD2yks1xftnKU=
|
||||
zombiezen.com/go/sqlite v1.4.0/go.mod h1:0w9F1DN9IZj9AcLS9YDKMboubCACkwYCGkzoy3eG5ik=
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
PACK_SERVER_OS_ARCHS = windows-amd64 darwin-amd64 darwin-arm64 linux-amd64
|
||||
PACK_SERVER_OS_ARCHS = windows-amd64 darwin-amd64 darwin-arm64 linux-amd64 linux-arm64
|
||||
prepare-pack-server:
|
||||
mkdir -p .release/
|
||||
|
||||
|
@ -6,11 +6,15 @@ pack-server-%:
|
|||
@OSARCH=$*; \
|
||||
if [ "$$OSARCH" = "windows-amd64" ]; then \
|
||||
BINARY_NAME=grpc-server.exe; \
|
||||
ARCHIVE_CMD="zip -r"; \
|
||||
ARCHIVE_FILE="js_$(VERSION)_$$OSARCH.zip"; \
|
||||
else \
|
||||
BINARY_NAME=grpc-server; \
|
||||
ARCHIVE_CMD="tar -czf"; \
|
||||
ARCHIVE_FILE="js_$(VERSION)_$$OSARCH.tar.gz"; \
|
||||
fi; \
|
||||
cp ./$$OSARCH* ./$$BINARY_NAME; \
|
||||
tar -czf js_$(VERSION)_$$OSARCH.tar.gz $$BINARY_NAME protobuf json; \
|
||||
mv js_$(VERSION)_$$OSARCH.tar.gz .release/
|
||||
$$ARCHIVE_CMD $$ARCHIVE_FILE $$BINARY_NAME protobuf json; \
|
||||
mv $$ARCHIVE_FILE .release/
|
||||
|
||||
pack-server: prepare-pack-server $(addprefix pack-server-,$(PACK_SERVER_OS_ARCHS))
|
||||
|
|
|
@ -41,4 +41,4 @@ setup-protoc-jsweb:
|
|||
mv deps/grpc-web/javascript/net/grpc/web/generator/protoc-gen-grpc-web deps/protoc-gen-grpc-web
|
||||
@rm -rf deps/grpc-web
|
||||
|
||||
setup-protoc: setup-protoc-go setup-protoc-jsweb
|
||||
setup-protoc: setup-protoc-go setup-protoc-jsweb
|
|
@ -149,7 +149,6 @@ func (c *client) recordAggregatedData() {
|
|||
toSend := c.aggregatableMap
|
||||
c.aggregatableMap = make(map[string]SamplableEvent)
|
||||
c.lock.Unlock()
|
||||
// итерейтим сразу старую мапу и скармливаем ГЦ
|
||||
for _, ev := range toSend {
|
||||
c.send(ev)
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cheggaaa/mb/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/valyala/fastjson"
|
||||
|
||||
"github.com/anyproto/anytype-heart/metrics/anymetry"
|
||||
|
@ -79,19 +79,19 @@ func TestClient_SendEvents(t *testing.T) {
|
|||
go c.startSendingBatchMessages(&testAppInfoProvider{})
|
||||
|
||||
c.send(&testEvent{})
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
assert.Equal(t, 1, c.batcher.Len())
|
||||
require.Equal(t, 1, c.batcher.Len())
|
||||
telemetry.AssertNotCalled(t, "SendEvents", mock.Anything, mock.Anything)
|
||||
|
||||
c.send(&testEvent{})
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
mutex.Lock()
|
||||
assert.Equal(t, 0, c.batcher.Len())
|
||||
assert.Equal(t, 2, len(events))
|
||||
require.Equal(t, 0, c.batcher.Len())
|
||||
require.Equal(t, 2, len(events))
|
||||
mutex.Unlock()
|
||||
|
||||
assert.True(t, events[0].GetTimestamp() > 0)
|
||||
require.True(t, events[0].GetTimestamp() > 0)
|
||||
telemetry.AssertCalled(t, "SendEvents", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
|
|
@ -48,132 +48,6 @@ func (t ReindexType) String() string {
|
|||
return "unknown"
|
||||
}
|
||||
|
||||
const IndexEventThresholdMs = 10
|
||||
|
||||
type IndexEvent struct {
|
||||
baseInfo
|
||||
ObjectId string
|
||||
IndexLinksTimeMs int64
|
||||
IndexDetailsTimeMs int64
|
||||
IndexSetRelationsTimeMs int64
|
||||
RelationsCount int
|
||||
DetailsCount int
|
||||
SetRelationsCount int
|
||||
}
|
||||
|
||||
func (c *IndexEvent) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *IndexEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
if c.IndexLinksTimeMs+c.IndexDetailsTimeMs+c.IndexSetRelationsTimeMs < IndexEventThresholdMs {
|
||||
return nil
|
||||
}
|
||||
|
||||
event, properties := setupProperties(arena, "index")
|
||||
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
properties.Set("links_ms", arena.NewNumberInt(int(c.IndexLinksTimeMs)))
|
||||
properties.Set("details_ms", arena.NewNumberInt(int(c.IndexDetailsTimeMs)))
|
||||
properties.Set("set_ms", arena.NewNumberInt(int(c.IndexSetRelationsTimeMs)))
|
||||
properties.Set("rel_count", arena.NewNumberInt(c.RelationsCount))
|
||||
properties.Set("det_count", arena.NewNumberInt(c.DetailsCount))
|
||||
properties.Set("set_rel_count", arena.NewNumberInt(c.SetRelationsCount))
|
||||
properties.Set("total_ms", arena.NewNumberInt(int(c.IndexLinksTimeMs+c.IndexDetailsTimeMs+c.IndexSetRelationsTimeMs)))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
const ReindexEventThresholdsMs = 100
|
||||
|
||||
type ReindexEvent struct {
|
||||
baseInfo
|
||||
ReindexType ReindexType
|
||||
Total int
|
||||
Succeed int
|
||||
SpentMs int
|
||||
IndexesRemoved bool
|
||||
}
|
||||
|
||||
func (c *ReindexEvent) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *ReindexEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
if c.SpentMs < ReindexEventThresholdsMs {
|
||||
return nil
|
||||
}
|
||||
|
||||
event, properties := setupProperties(arena, "store_reindex")
|
||||
|
||||
properties.Set("spent_ms", arena.NewNumberInt(c.SpentMs))
|
||||
properties.Set("total", arena.NewNumberInt(c.Total))
|
||||
properties.Set("failed", arena.NewNumberInt(c.Total-c.Succeed))
|
||||
properties.Set("type", arena.NewNumberInt(int(c.ReindexType)))
|
||||
var isRemoved *fastjson.Value
|
||||
if c.IndexesRemoved {
|
||||
isRemoved = arena.NewTrue()
|
||||
} else {
|
||||
isRemoved = arena.NewFalse()
|
||||
}
|
||||
properties.Set("ix_removed", isRemoved)
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
const BlockSplitEventThresholdsMs = 10
|
||||
|
||||
type BlockSplit struct {
|
||||
baseInfo
|
||||
AlgorithmMs int64
|
||||
ApplyMs int64
|
||||
ObjectId string
|
||||
}
|
||||
|
||||
func (c *BlockSplit) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *BlockSplit) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
if c.ApplyMs+c.AlgorithmMs < BlockSplitEventThresholdsMs {
|
||||
return nil
|
||||
}
|
||||
|
||||
event, properties := setupProperties(arena, "block_merge")
|
||||
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
properties.Set("algorithm_ms", arena.NewNumberInt(int(c.AlgorithmMs)))
|
||||
properties.Set("apply_ms", arena.NewNumberInt(int(c.ApplyMs)))
|
||||
properties.Set("total_ms", arena.NewNumberInt(int(c.AlgorithmMs+c.ApplyMs)))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
type TreeBuild struct {
|
||||
baseInfo
|
||||
SbType uint64
|
||||
TimeMs int64
|
||||
ObjectId string
|
||||
Logs int
|
||||
Request string
|
||||
}
|
||||
|
||||
func (c *TreeBuild) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *TreeBuild) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "tree_build")
|
||||
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
properties.Set("logs", arena.NewNumberInt(c.Logs))
|
||||
properties.Set("request", arena.NewString(c.Request))
|
||||
properties.Set("time_ms", arena.NewNumberInt(int(c.TimeMs)))
|
||||
properties.Set("sb_type", arena.NewNumberInt(int(c.SbType)))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
func setupProperties(arena *fastjson.Arena, eventType string) (*fastjson.Value, *fastjson.Value) {
|
||||
event := arena.NewObject()
|
||||
properties := arena.NewObject()
|
||||
|
@ -182,153 +56,6 @@ func setupProperties(arena *fastjson.Arena, eventType string) (*fastjson.Value,
|
|||
return event, properties
|
||||
}
|
||||
|
||||
const StateApplyThresholdMs = 100
|
||||
|
||||
type StateApply struct {
|
||||
baseInfo
|
||||
BeforeApplyMs int64
|
||||
StateApplyMs int64
|
||||
PushChangeMs int64
|
||||
ReportChangeMs int64
|
||||
ApplyHookMs int64
|
||||
ObjectId string
|
||||
}
|
||||
|
||||
func (c *StateApply) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *StateApply) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
total := c.StateApplyMs + c.PushChangeMs + c.BeforeApplyMs + c.ApplyHookMs + c.ReportChangeMs
|
||||
if total <= StateApplyThresholdMs {
|
||||
return nil
|
||||
}
|
||||
event, properties := setupProperties(arena, "state_apply")
|
||||
|
||||
properties.Set("before_ms", arena.NewNumberInt(int(c.BeforeApplyMs)))
|
||||
properties.Set("apply_ms", arena.NewNumberInt(int(c.StateApplyMs)))
|
||||
properties.Set("push_ms", arena.NewNumberInt(int(c.PushChangeMs)))
|
||||
properties.Set("report_ms", arena.NewNumberInt(int(c.ReportChangeMs)))
|
||||
properties.Set("hook_ms", arena.NewNumberInt(int(c.ApplyHookMs)))
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
properties.Set("total_ms", arena.NewNumberInt(int(c.StateApplyMs+c.PushChangeMs+c.BeforeApplyMs+c.ApplyHookMs+c.ReportChangeMs)))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
type AppStart struct {
|
||||
baseInfo
|
||||
Request string
|
||||
TotalMs int64
|
||||
PerCompMs map[string]int64
|
||||
Extra map[string]interface{}
|
||||
}
|
||||
|
||||
func (c *AppStart) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *AppStart) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "app_start")
|
||||
|
||||
properties.Set("request", arena.NewString(c.Request))
|
||||
properties.Set("time_ms", arena.NewNumberInt(int(c.TotalMs)))
|
||||
for comp, ms := range c.PerCompMs {
|
||||
properties.Set("spent_"+comp, arena.NewNumberInt(int(ms)))
|
||||
}
|
||||
|
||||
for key, val := range c.Extra {
|
||||
switch val := val.(type) {
|
||||
case string:
|
||||
properties.Set(key, arena.NewString(val))
|
||||
case int64:
|
||||
properties.Set(key, arena.NewNumberInt(int(val)))
|
||||
}
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
type BlockMerge struct {
|
||||
baseInfo
|
||||
AlgorithmMs int64
|
||||
ApplyMs int64
|
||||
ObjectId string
|
||||
}
|
||||
|
||||
func (c *BlockMerge) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *BlockMerge) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "block_split")
|
||||
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
properties.Set("algorithm_ms", arena.NewNumberInt(int(c.AlgorithmMs)))
|
||||
properties.Set("apply_ms", arena.NewNumberInt(int(c.ApplyMs)))
|
||||
properties.Set("total_ms", arena.NewNumberInt(int(c.AlgorithmMs+c.ApplyMs)))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
type CreateObjectEvent struct {
|
||||
baseInfo
|
||||
SetDetailsMs int64
|
||||
GetWorkspaceBlockWaitMs int64
|
||||
WorkspaceCreateMs int64
|
||||
SmartblockCreateMs int64
|
||||
SmartblockType int
|
||||
ObjectId string
|
||||
}
|
||||
|
||||
func (c *CreateObjectEvent) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *CreateObjectEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "create_object")
|
||||
|
||||
properties.Set("set_details_ms", arena.NewNumberInt(int(c.SetDetailsMs)))
|
||||
properties.Set("get_workspace_block_wait_ms", arena.NewNumberInt(int(c.GetWorkspaceBlockWaitMs)))
|
||||
properties.Set("workspace_create_ms", arena.NewNumberInt(int(c.WorkspaceCreateMs)))
|
||||
properties.Set("smartblock_create_ms", arena.NewNumberInt(int(c.SmartblockCreateMs)))
|
||||
properties.Set("total_ms", arena.NewNumberInt(int(c.SetDetailsMs+c.GetWorkspaceBlockWaitMs+c.WorkspaceCreateMs+c.SmartblockCreateMs)))
|
||||
properties.Set("smartblock_type", arena.NewNumberInt(c.SmartblockType))
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
type OpenBlockEvent struct {
|
||||
baseInfo
|
||||
GetBlockMs int64
|
||||
DataviewMs int64
|
||||
ApplyMs int64
|
||||
ShowMs int64
|
||||
FileWatcherMs int64
|
||||
SmartblockType int
|
||||
ObjectId string
|
||||
}
|
||||
|
||||
func (c *OpenBlockEvent) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *OpenBlockEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "open_block")
|
||||
|
||||
properties.Set("object_id", arena.NewString(c.ObjectId))
|
||||
properties.Set("get_block_ms", arena.NewNumberInt(int(c.GetBlockMs)))
|
||||
properties.Set("dataview_notify_ms", arena.NewNumberInt(int(c.DataviewMs)))
|
||||
properties.Set("apply_ms", arena.NewNumberInt(int(c.ApplyMs)))
|
||||
properties.Set("show_ms", arena.NewNumberInt(int(c.ShowMs)))
|
||||
properties.Set("file_watchers_ms", arena.NewNumberInt(int(c.FileWatcherMs)))
|
||||
properties.Set("total_ms", arena.NewNumberInt(int(c.GetBlockMs+c.DataviewMs+c.ApplyMs+c.ShowMs+c.FileWatcherMs)))
|
||||
properties.Set("smartblock_type", arena.NewNumberInt(c.SmartblockType))
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
type ImportStartedEvent struct {
|
||||
baseInfo
|
||||
ID string
|
||||
|
@ -401,22 +128,31 @@ func (c *MethodEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent
|
|||
return event
|
||||
}
|
||||
|
||||
type LongMethodEvent struct {
|
||||
type ChangeEvent struct {
|
||||
baseInfo
|
||||
methodName string
|
||||
middleTime int64
|
||||
stack string
|
||||
ChangeName string
|
||||
SbType string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (c *LongMethodEvent) GetBackend() anymetry.MetricsBackend {
|
||||
func (c *ChangeEvent) Key() string {
|
||||
return c.ChangeName
|
||||
}
|
||||
|
||||
func (c *ChangeEvent) Aggregate(other SamplableEvent) SamplableEvent {
|
||||
o := other.(*ChangeEvent)
|
||||
c.Count += o.Count
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ChangeEvent) GetBackend() anymetry.MetricsBackend {
|
||||
return inhouse
|
||||
}
|
||||
|
||||
func (c *LongMethodEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "LongMethodEvent")
|
||||
|
||||
properties.Set("methodName", arena.NewString(c.methodName))
|
||||
properties.Set("middleTime", arena.NewNumberInt(int(c.middleTime)))
|
||||
properties.Set("stack", arena.NewString(c.stack))
|
||||
func (c *ChangeEvent) MarshalFastJson(arena *fastjson.Arena) anymetry.JsonEvent {
|
||||
event, properties := setupProperties(arena, "ChangeEvent")
|
||||
properties.Set("changeName", arena.NewString(c.ChangeName))
|
||||
properties.Set("sbType", arena.NewString(c.SbType))
|
||||
properties.Set("count", arena.NewNumberInt(c.Count))
|
||||
return event
|
||||
}
|
||||
|
|
|
@ -230,14 +230,6 @@ func SharedLongMethodsInterceptor(ctx context.Context, req any, methodName strin
|
|||
Warnf("grpc unary request took too long")
|
||||
cache.addMethod(methodName)
|
||||
}
|
||||
|
||||
Service.Send(
|
||||
&LongMethodEvent{
|
||||
methodName: methodName,
|
||||
middleTime: time.Since(start).Milliseconds(),
|
||||
stack: debug.ParseGoroutinesDump(lastTrace.String(), "core.(*Middleware)."+methodName),
|
||||
},
|
||||
)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
|
|
@ -16,9 +16,10 @@ import (
|
|||
var (
|
||||
Service = NewService()
|
||||
clientMetricsLog = logging.Logger("service-metrics")
|
||||
sendInterval = 10.0 * time.Second
|
||||
sendInterval = 30.0 * time.Second
|
||||
maxTimeout = 30 * time.Second
|
||||
bufferSize = 500
|
||||
eventsLimit = 1000 // throttle
|
||||
)
|
||||
|
||||
// First constants must repeat syncstatus.SyncStatus constants for
|
||||
|
@ -200,7 +201,7 @@ func (s *service) Run() {
|
|||
|
||||
for _, c := range s.clients {
|
||||
c.ctx, c.cancel = context.WithCancel(context.Background())
|
||||
c.setBatcher(mb.New[anymetry.Event](0))
|
||||
c.setBatcher(mb.New[anymetry.Event](eventsLimit))
|
||||
go c.startAggregating()
|
||||
go c.startSendingBatchMessages(s)
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue