-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove the 1000 files limit when syncing from Desktop, Obsidian clien…
…ts (#605) ### Major - Push 1000 files at a time from the Desktop client for indexing - Push 1000 files at a time from the Obsidian client for indexing - Test 1000 file upload limit to index/update API endpoint ### Minor - Show relevant error message in desktop app, e.g when can't connect to server - Pass indexed filenames in API response for client validation - Collect files to index in single dict to simplify index/update controller Resolves #573
- Loading branch information
Showing
5 changed files
with
112 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,8 +114,8 @@ function processDirectory(filesToPush, folder) { | |
const files = fs.readdirSync(folder.path, { withFileTypes: true, recursive: true }); | ||
|
||
for (const file of files) { | ||
console.log(file); | ||
if (file.isFile() && validFileTypes.includes(file.name.split('.').pop())) { | ||
console.log(`Add ${file.name} in ${folder.path} for indexing`); | ||
filesToPush.push(path.join(folder.path, file.name)); | ||
} | ||
|
||
|
@@ -151,7 +151,7 @@ function pushDataToKhoj (regenerate = false) { | |
} | ||
|
||
const lastSync = store.get('lastSync') || []; | ||
const formData = new FormData(); | ||
const filesDataToPush = []; | ||
for (const file of filesToPush) { | ||
const stats = fs.statSync(file); | ||
if (!regenerate) { | ||
|
@@ -167,7 +167,7 @@ function pushDataToKhoj (regenerate = false) { | |
let mimeType = filenameToMimeType(file) + (encoding === "utf8" ? "; charset=UTF-8" : ""); | ||
let fileContent = Buffer.from(fs.readFileSync(file, { encoding: encoding }), encoding); | ||
let fileObj = new Blob([fileContent], { type: mimeType }); | ||
formData.append('files', fileObj, file); | ||
filesDataToPush.push({blob: fileObj, path: file}); | ||
state[file] = { | ||
success: true, | ||
} | ||
|
@@ -184,52 +184,51 @@ function pushDataToKhoj (regenerate = false) { | |
for (const syncedFile of lastSync) { | ||
if (!filesToPush.includes(syncedFile.path)) { | ||
fileObj = new Blob([""], { type: filenameToMimeType(syncedFile.path) }); | ||
formData.append('files', fileObj, syncedFile.path); | ||
filesDataToPush.push({blob: fileObj, path: syncedFile.path}); | ||
} | ||
} | ||
|
||
// Send collected files to Khoj server for indexing | ||
if (!!formData?.entries()?.next().value) { | ||
const hostURL = store.get('hostURL') || KHOJ_URL; | ||
const headers = { | ||
'Authorization': `Bearer ${store.get("khojToken")}` | ||
}; | ||
axios.post(`${hostURL}/api/v1/index/update?force=${regenerate}&client=desktop`, formData, { headers }) | ||
.then(response => { | ||
console.log(response.data); | ||
let lastSync = []; | ||
for (const file of filesToPush) { | ||
lastSync.push({ | ||
path: file, | ||
datetime: new Date().toISOString() | ||
}); | ||
} | ||
store.set('lastSync', lastSync); | ||
}) | ||
.catch(error => { | ||
console.error(error); | ||
if (error.code == 'ECONNREFUSED') { | ||
const win = BrowserWindow.getAllWindows()[0]; | ||
if (win) win.webContents.send('update-state', state); | ||
} else if (error.response.status == 429) { | ||
const win = BrowserWindow.getAllWindows()[0]; | ||
if (win) win.webContents.send('needsSubscription', true); | ||
if (win) win.webContents.send('update-state', state); | ||
} | ||
state['completed'] = false | ||
}) | ||
.finally(() => { | ||
// Syncing complete | ||
syncing = false; | ||
const win = BrowserWindow.getAllWindows()[0]; | ||
if (win) win.webContents.send('update-state', state); | ||
}); | ||
} else { | ||
const hostURL = store.get('hostURL') || KHOJ_URL; | ||
const headers = { 'Authorization': `Bearer ${store.get("khojToken")}` }; | ||
let requests = []; | ||
|
||
// Request indexing files on server. With upto 1000 files in each request | ||
for (let i = 0; i < filesDataToPush.length; i += 1000) { | ||
const filesDataGroup = filesDataToPush.slice(i, i + 1000); | ||
const formData = new FormData(); | ||
filesDataGroup.forEach(fileData => { formData.append('files', fileData.blob, fileData.path) }); | ||
let request = axios.post(`${hostURL}/api/v1/index/update?force=${regenerate}&client=desktop`, formData, { headers }); | ||
requests.push(request); | ||
} | ||
|
||
// Wait for requests batch to finish | ||
Promise | ||
.all(requests) | ||
.then(responses => { | ||
const lastSync = filesToPush | ||
.filter(file => responses.find(response => response.data.includes(file))) | ||
.map(file => ({ path: file, datetime: new Date().toISOString() })); | ||
store.set('lastSync', lastSync); | ||
}) | ||
.catch(error => { | ||
console.error(error); | ||
state["completed"] = false; | ||
if (error?.response?.status === 429 && (win = BrowserWindow.getAllWindows()[0])) { | ||
state["error"] = `Looks like you're out of space to sync your files. <a href="https://app.khoj.dev/config">Upgrade your plan</a> to unlock more space.`; | ||
} else if (error?.code === 'ECONNREFUSED') { | ||
state["error"] = `Could not connect to Khoj server. Ensure you can connect to it at ${error.address}:${error.port}.`; | ||
} else { | ||
state["error"] = `Sync was unsuccessful at ${currentTime.toLocaleTimeString()}. Contact [email protected] to report this issue.`; | ||
} | ||
}) | ||
.finally(() => { | ||
// Syncing complete | ||
syncing = false; | ||
const win = BrowserWindow.getAllWindows()[0]; | ||
if (win) win.webContents.send('update-state', state); | ||
} | ||
if (win = BrowserWindow.getAllWindows()[0]) { | ||
win.webContents.send('update-state', state); | ||
} | ||
}); | ||
} | ||
|
||
pushDataToKhoj(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -158,7 +158,7 @@ window.updateStateAPI.onUpdateState((event, state) => { | |
nextSyncTime = new Date(); | ||
nextSyncTime.setMinutes(Math.ceil((nextSyncTime.getMinutes() + 1) / 10) * 10); | ||
if (state.completed == false) { | ||
syncStatusElement.innerHTML = `Sync was unsuccessful at ${currentTime.toLocaleTimeString()}. Contact [email protected] to report this issue.`; | ||
if (state.error) syncStatusElement.innerHTML = state.error; | ||
return; | ||
} | ||
const options = { hour: '2-digit', minute: '2-digit' }; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters