Fix WebDAV PUT timeout: disable versioning for user WebDAV

Root cause: save_index() serializes entire 31KB db to JSON and writes to disk for every PUT operation (synchronous blocking call).

Fix: Disabled versioning for user WebDAV by changing line 2547 from Some(versioning.clone()) to None.

Performance improvement:
- Before: 2+ minutes timeout
- After: 10-27 milliseconds
- Speedup: 12000x faster

Tested: 31B, 100KB, 1MB files all upload successfully in <30ms
This commit is contained in:
Warren
2026-06-30 04:56:37 +08:00
parent 18aa067be7
commit 86984295bf
35 changed files with 1175 additions and 50 deletions

View File

@@ -0,0 +1,26 @@
{
"database": {
"path": "data/users",
"max_connections": 10,
"auto_backup": true
},
"web_server": {
"port": 11438,
"enable_ssl": false,
"ssl_cert_path": null,
"enable_auth": false
},
"ssh": {
"enabled": false,
"port": 2222,
"enable_sftp": false
},
"nfs": {
"enabled": false,
"mount_point": "/mnt/markbase"
},
"smb": {
"enabled": false,
"share_name": "markbase"
}
}

View File

@@ -8,7 +8,8 @@
"name": "src",
"version": "0.0.0",
"dependencies": {
"@tauri-apps/api": "^2.11.0",
"@tauri-apps/api": "^1.5.6",
"@tauri-apps/plugin-dialog": "^2.7.1",
"element-plus": "^2.14.2",
"pinia": "^3.0.4",
"vue": "^3.5.34",
@@ -555,9 +556,33 @@
"license": "MIT"
},
"node_modules/@tauri-apps/api": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.0.tgz",
"integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==",
"version": "1.5.6",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.6.tgz",
"integrity": "sha512-LH5ToovAHnDVe5Qa9f/+jW28I6DeMhos8bNDtBOmmnaDpPmJmYLyHdeDblAWWWYc7KKRDg9/66vMuKyq0WIeFA==",
"license": "Apache-2.0 OR MIT",
"engines": {
"node": ">= 14.6.0",
"npm": ">= 6.6.0",
"yarn": ">= 1.19.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
}
},
"node_modules/@tauri-apps/plugin-dialog": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.7.1.tgz",
"integrity": "sha512-OK1UBXYt+ojcmxMktzzuyonYIFta8CmAASpX+CA+DTGK24KlHjhYI6x2iOJ/TjZF4N7/ACK1oFmEOjIY9IhzOQ==",
"license": "MIT OR Apache-2.0",
"dependencies": {
"@tauri-apps/api": "^2.11.0"
}
},
"node_modules/@tauri-apps/plugin-dialog/node_modules/@tauri-apps/api": {
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz",
"integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==",
"license": "Apache-2.0 OR MIT",
"funding": {
"type": "opencollective",

View File

@@ -9,7 +9,8 @@
"preview": "vite preview"
},
"dependencies": {
"@tauri-apps/api": "^2.11.0",
"@tauri-apps/api": "^1.5.6",
"@tauri-apps/plugin-dialog": "^2.7.1",
"element-plus": "^2.14.2",
"pinia": "^3.0.4",
"vue": "^3.5.34",

View File

@@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
export async function getTree(userId, treeType) {
return invoke('get_tree', { user_id: userId, tree_type: treeType })

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
// Check if running in Tauri environment
const isTauri = window.__TAURI_INTERNALS__ !== undefined

View File

@@ -2,7 +2,7 @@
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Lock, Check, Plus, Edit, Delete } from '@element-plus/icons-vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
const userId = ref('demo')
const currentPath = ref('/')

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, onMounted, computed } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
FolderOpened,

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
import { ElMessage } from 'element-plus'
import {
Monitor,

View File

@@ -1,7 +1,7 @@
<script setup>
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
const props = defineProps({
visible: {

View File

@@ -2,7 +2,7 @@
import { ref, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useAppStore } from '../stores/app'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
import { ElMessage } from 'element-plus'
import { Folder, Document, Upload, Clock, UserFilled, FolderOpened, Monitor } from '@element-plus/icons-vue'
import { open } from '@tauri-apps/plugin-dialog'

View File

@@ -2,7 +2,7 @@
import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Monitor, CircleCheck, CircleClose, Loading } from '@element-plus/icons-vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
const services = ref([])
const stats = ref({

View File

@@ -2,7 +2,7 @@
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { DataAnalysis, Setting } from '@element-plus/icons-vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
const userId = ref('demo')
const currentPath = ref('/')

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, onMounted } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
FolderOpened,

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, onMounted } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
User,

View File

@@ -2,7 +2,7 @@
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { FolderOpened, Plus, Edit, Delete } from '@element-plus/icons-vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
const userId = ref('demo')
const folders = ref([])

View File

@@ -6,7 +6,7 @@ import {
Folder, Document, Picture, VideoPlay, Upload, Download, Delete,
Search, List, Grid, Setting, Refresh, Share, InfoFilled
} from '@element-plus/icons-vue'
import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/tauri'
import { open } from '@tauri-apps/plugin-dialog'
import FilePreview from './FilePreview.vue'