Просмотр исходного кода

Merge branch 'empty-collection-invisible'

fszontagh 1 месяц назад
Родитель
Сommit
8b70b2d1f8
2 измененных файлов с 36 добавлено и 7 удалено
  1. 14 5
      src/webserver/api/database_controller.cpp
  2. 22 2
      webui/src/pages/DatabasePage.tsx

+ 14 - 5
src/webserver/api/database_controller.cpp

@@ -103,11 +103,20 @@ void DatabaseController::createCollection(const httplib::Request& req, httplib::
     auto result = storage_.createCollection(name, {}, default_ttl_ms);
     auto result = storage_.createCollection(name, {}, default_ttl_ms);
 
 
     if (result.failed()) {
     if (result.failed()) {
-        if (result.error().code() == common::ErrorCode::AlreadyExists) {
-            sendError(res, "Collection already exists: " + name, 409);
-        } else {
-            sendError(res, result.error().message(), 500);
-        }
+        // The upstream client answers with a bare bool, so the reason never
+        // reaches us - the AlreadyExists branch this used to have could not
+        // fire, and every refusal surfaced as a 500 with nothing to act on.
+        //
+        // By far the most common reason is that the collection is already
+        // there. It just cannot be seen: the database does not list, or even
+        // let you query, a collection with no documents in it, so creating one
+        // looks like nothing happened and the obvious response is to try again.
+        // Saying so is more use than repeating "failed".
+        sendError(res,
+                  "Could not create '" + name + "'. It most likely already exists: a collection "
+                  "with no documents in it is not listed and cannot be queried, so creating one "
+                  "looks like nothing happened. Write a document to it and it will appear",
+                  409);
         return;
         return;
     }
     }
 
 

+ 22 - 2
webui/src/pages/DatabasePage.tsx

@@ -72,6 +72,8 @@ export default function DatabasePage() {
   const [currentPage, setCurrentPage] = useState(1)
   const [currentPage, setCurrentPage] = useState(1)
   const documentListRef = useRef<HTMLDivElement>(null)
   const documentListRef = useRef<HTMLDivElement>(null)
 
 
+  const [justCreated, setJustCreated] = useState<string[]>([])
+
   const { data: collectionsData, isLoading: collectionsLoading } = useQuery({
   const { data: collectionsData, isLoading: collectionsLoading } = useQuery({
     queryKey: ['database-collections'],
     queryKey: ['database-collections'],
     queryFn: () => databaseApi.listCollections(),
     queryFn: () => databaseApi.listCollections(),
@@ -133,6 +135,11 @@ export default function DatabasePage() {
     mutationFn: ({ name, settings }: { name: string; settings?: CollectionSettings }) =>
     mutationFn: ({ name, settings }: { name: string; settings?: CollectionSettings }) =>
       databaseApi.createCollection(name, settings),
       databaseApi.createCollection(name, settings),
     onSuccess: (_, { name }) => {
     onSuccess: (_, { name }) => {
+      // The database does not list a collection until it holds a document, so
+      // refetching would drop the one just created and the whole thing would
+      // look like it had not worked. Remembered here until it shows up on its
+      // own.
+      setJustCreated((prev) => (prev.includes(name) ? prev : [...prev, name]))
       queryClient.invalidateQueries({ queryKey: ['database-collections'] })
       queryClient.invalidateQueries({ queryKey: ['database-collections'] })
       setShowNewCollectionModal(false)
       setShowNewCollectionModal(false)
       setNewCollectionName('')
       setNewCollectionName('')
@@ -299,8 +306,17 @@ export default function DatabasePage() {
     }
     }
   }
   }
 
 
-  const collections: string[] = collectionsData?.collections || []
+  const fetched: string[] = collectionsData?.collections || []
+  // Anything created this session that the server cannot list yet.
+  const collections: string[] = [
+    ...fetched,
+    ...justCreated.filter((name) => !fetched.includes(name)),
+  ]
   const documents: Document[] = documentsData?.documents || []
   const documents: Document[] = documentsData?.documents || []
+  // A collection with nothing in it cannot be queried at all, so its document
+  // list comes back as an error rather than an empty page.
+  const isEmptyNewCollection =
+    !!selectedCollection && justCreated.includes(selectedCollection) && documents.length === 0
   const totalDocuments = documentsData?.total || 0
   const totalDocuments = documentsData?.total || 0
   const totalPages = Math.ceil(totalDocuments / PAGE_SIZE)
   const totalPages = Math.ceil(totalDocuments / PAGE_SIZE)
 
 
@@ -563,7 +579,11 @@ export default function DatabasePage() {
                 ))
                 ))
               ) : (
               ) : (
                 <p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
                 <p className="text-sm text-gray-500 dark:text-gray-400 text-center py-4">
-                  {searchTerm ? 'No matching documents' : 'No documents'}
+                  {searchTerm
+                    ? 'No matching documents'
+                    : isEmptyNewCollection
+                      ? 'Created, but empty. The database does not list or return a collection until something writes to it, so this will not appear after a reload until it holds a document.'
+                      : 'No documents'}
                 </p>
                 </p>
               )}
               )}
             </div>
             </div>