From ef5c90a28328f88e5711ed8dc6b2cd68ba92ee17 Mon Sep 17 00:00:00 2001
From: RosyDev <rosy@rosy-logic.ch>
Date: Wed, 24 Apr 2024 08:49:34 +0200
Subject: [PATCH] HTTP library reload cache, if cach if the cache is empty,
 when pick a part

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17569
---
 eeschema/sch_io/http_lib/sch_io_http_lib.cpp | 118 ++++++++++---------
 eeschema/sch_io/http_lib/sch_io_http_lib.h   |  13 +-
 2 files changed, 69 insertions(+), 62 deletions(-)

diff --git a/eeschema/sch_io/http_lib/sch_io_http_lib.cpp b/eeschema/sch_io/http_lib/sch_io_http_lib.cpp
index 557e1c4f327..3af35e5354d 100644
--- a/eeschema/sch_io/http_lib/sch_io_http_lib.cpp
+++ b/eeschema/sch_io/http_lib/sch_io_http_lib.cpp
@@ -29,8 +29,7 @@
 #include "sch_io_http_lib.h"
 
 
-SCH_IO_HTTP_LIB::SCH_IO_HTTP_LIB() : SCH_IO( wxS( "HTTP library" ) ),
-    m_libTable( nullptr )
+SCH_IO_HTTP_LIB::SCH_IO_HTTP_LIB() : SCH_IO( wxS( "HTTP library" ) ), m_libTable( nullptr )
 {
 }
 
@@ -56,11 +55,11 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
                                           const wxString&           aLibraryPath,
                                           const STRING_UTF8_MAP*    aProperties )
 {
-    wxCHECK_RET( m_libTable, _("httplib plugin missing library table handle!") );
+    wxCHECK_RET( m_libTable, _( "httplib plugin missing library table handle!" ) );
     ensureSettings( aLibraryPath );
     ensureConnection();
 
-    if( !m_conn)
+    if( !m_conn )
     {
         THROW_IO_ERROR( m_lastError );
         return;
@@ -70,13 +69,11 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
             ( aProperties
               && aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
 
-    for(const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
+    for( const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
     {
         bool refresh_cache = true;
 
-        std::vector<HTTP_LIB_PART> found_parts;
-
-         // Check if there is already a part in our cache, if not fetch it
+        // Check if there is already a part in our cache, if not fetch it
         if( m_cachedCategories.find( category.id ) != m_cachedCategories.end() )
         {
             // check if it's outdated, if so re-fetch
@@ -89,26 +86,7 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
 
         if( refresh_cache )
         {
-            if( !m_conn->SelectAll( category, found_parts ) )
-            {
-                if( !m_conn->GetLastError().empty() )
-                {
-                    wxString msg =
-                            wxString::Format( _( "Error retriving data from HTTP library %s: %s" ),
-                                              category.name, m_conn->GetLastError() );
-                    THROW_IO_ERROR( msg );
-                }
-
-                continue;
-            }
-
-            // remove cached parts
-            m_cachedCategories[category.id].cachedParts.clear();
-
-            // Copy newly cached data across
-            m_cachedCategories[category.id].cachedParts = found_parts;
-            m_cachedCategories[category.id].lastCached = std::time( nullptr );
-
+            syncCache( category );
         }
 
         for( const HTTP_LIB_PART& part : m_cachedCategories[category.id].cachedParts )
@@ -119,14 +97,12 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
 
             if( symbol && ( !powerSymbolsOnly || symbol->IsPower() ) )
                 aSymbolList.emplace_back( symbol );
-
         }
     }
 }
 
 
-LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString&        aLibraryPath,
-                                         const wxString&        aAliasName,
+LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
                                          const STRING_UTF8_MAP* aProperties )
 {
     wxCHECK( m_libTable, nullptr );
@@ -145,13 +121,17 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString&        aLibraryPath,
 
     std::vector<HTTP_LIB_CATEGORY> categories = m_conn->getCategories();
 
-    std::tuple relations = m_conn->getCachedParts()[partName];
+    if( m_conn->getCachedParts().empty() )
+    {
+        syncCache();
+    }
+
+    std::tuple  relations = m_conn->getCachedParts()[partName];
+    std::string associatedCatID = std::get<1>( relations );
 
     // get the matching category
     for( const HTTP_LIB_CATEGORY& categoryIter : categories )
     {
-        std::string associatedCatID = std::get<1>( relations );
-
         if( categoryIter.id == associatedCatID )
         {
             foundCategory = &categoryIter;
@@ -197,26 +177,26 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString&        aLibraryPath,
 
 void SCH_IO_HTTP_LIB::GetSubLibraryNames( std::vector<wxString>& aNames )
 {
-     ensureSettings( wxEmptyString );
+    ensureSettings( wxEmptyString );
 
-     aNames.clear();
+    aNames.clear();
 
-     std::set<wxString> categoryNames;
+    std::set<wxString> categoryNames;
 
-     for( const HTTP_LIB_CATEGORY& categoryIter : m_conn->getCategories() )
-     {
+    for( const HTTP_LIB_CATEGORY& categoryIter : m_conn->getCategories() )
+    {
         if( categoryNames.count( categoryIter.name ) )
             continue;
 
         aNames.emplace_back( categoryIter.name );
         categoryNames.insert( categoryIter.name );
-     }
+    }
 }
 
 
 void SCH_IO_HTTP_LIB::GetAvailableSymbolFields( std::vector<wxString>& aNames )
 {
-     // TODO: Implement this sometime; This is currently broken...
+    // TODO: Implement this sometime; This is currently broken...
     std::copy( m_customFields.begin(), m_customFields.end(), std::back_inserter( aNames ) );
 }
 
@@ -230,13 +210,12 @@ void SCH_IO_HTTP_LIB::GetDefaultSymbolFields( std::vector<wxString>& aNames )
 
 void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
 {
-
     auto tryLoad = [&]()
     {
         if( !m_settings->LoadFromFile() )
         {
-            wxString msg = wxString::Format( _( "HTTP library settings file %s missing or invalid" ),
-                                             aSettingsPath );
+            wxString msg = wxString::Format(
+                    _( "HTTP library settings file %s missing or invalid" ), aSettingsPath );
 
             THROW_IO_ERROR( msg );
         }
@@ -252,11 +231,10 @@ void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
 
         if( m_settings->getSupportedAPIVersion() != m_settings->m_Source.api_version )
         {
-            wxString msg = wxString::Format(
-                    _( "HTTP library settings file %s uses API version %s, but KiCad requires version %s" ),
-                    aSettingsPath,
-                    m_settings->m_Source.api_version,
-                    m_settings->getSupportedAPIVersion() );
+            wxString msg = wxString::Format( _( "HTTP library settings file %s uses API version "
+                                                "%s, but KiCad requires version %s" ),
+                                             aSettingsPath, m_settings->m_Source.api_version,
+                                             m_settings->getSupportedAPIVersion() );
 
             THROW_IO_ERROR( msg );
         }
@@ -264,8 +242,7 @@ void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
         if( m_settings->m_Source.root_url.empty() )
         {
             wxString msg = wxString::Format(
-                    _( "HTTP library settings file %s is missing the root URL!" ),
-                    aSettingsPath );
+                    _( "HTTP library settings file %s is missing the root URL!" ), aSettingsPath );
 
             THROW_IO_ERROR( msg );
         }
@@ -290,7 +267,6 @@ void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
 
         // Append api version to root URL
         m_settings->m_Source.root_url += m_settings->m_Source.api_version + "/";
-
     };
 
     if( !m_settings && !aSettingsPath.IsEmpty() )
@@ -322,9 +298,8 @@ void SCH_IO_HTTP_LIB::ensureConnection()
 
     if( !m_conn || !m_conn->IsValidEndpoint() )
     {
-        wxString msg = wxString::Format(
-                _( "Could not connect to %s. Errors: %s" ),
-                m_settings->m_Source.root_url, m_lastError );
+        wxString msg = wxString::Format( _( "Could not connect to %s. Errors: %s" ),
+                                         m_settings->m_Source.root_url, m_lastError );
 
         THROW_IO_ERROR( msg );
     }
@@ -351,6 +326,38 @@ void SCH_IO_HTTP_LIB::connect()
     }
 }
 
+void SCH_IO_HTTP_LIB::syncCache()
+{
+    for( const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
+    {
+        syncCache( category );
+    }
+}
+
+void SCH_IO_HTTP_LIB::syncCache( const HTTP_LIB_CATEGORY& category )
+{
+    std::vector<HTTP_LIB_PART> found_parts;
+
+    if( !m_conn->SelectAll( category, found_parts ) )
+    {
+        if( !m_conn->GetLastError().empty() )
+        {
+            wxString msg = wxString::Format( _( "Error retriving data from HTTP library %s: %s" ),
+                                             category.name, m_conn->GetLastError() );
+            THROW_IO_ERROR( msg );
+        }
+
+        return;
+    }
+
+    // remove cached parts
+    m_cachedCategories[category.id].cachedParts.clear();
+
+    // Copy newly cached data across
+    m_cachedCategories[category.id].cachedParts = found_parts;
+    m_cachedCategories[category.id].lastCached = std::time( nullptr );
+}
+
 
 LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString&          aSymbolName,
                                                  const HTTP_LIB_CATEGORY& aCategory,
@@ -483,7 +490,6 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString&          aSymbo
 
                 m_customFields.insert( fieldName );
             }
-
         }
     }
 
diff --git a/eeschema/sch_io/http_lib/sch_io_http_lib.h b/eeschema/sch_io/http_lib/sch_io_http_lib.h
index 3d7e3cb9409..4bc537c85f1 100644
--- a/eeschema/sch_io/http_lib/sch_io_http_lib.h
+++ b/eeschema/sch_io/http_lib/sch_io_http_lib.h
@@ -78,20 +78,22 @@ public:
     const wxString& GetError() const override { return m_lastError; }
 
 private:
-
     void ensureSettings( const wxString& aSettingsPath );
 
     void ensureConnection();
 
     void connect();
 
-    LIB_SYMBOL* loadSymbolFromPart( const wxString& aSymbolName,
-                                    const HTTP_LIB_CATEGORY& aCategory,
+    void syncCache();
+
+    void syncCache( const HTTP_LIB_CATEGORY& category );
+
+    LIB_SYMBOL* loadSymbolFromPart( const wxString& aSymbolName, const HTTP_LIB_CATEGORY& aCategory,
                                     const HTTP_LIB_PART& aPart );
 
     SYMBOL_LIB_TABLE* m_libTable;
 
-     /// Generally will be null if no valid connection is established
+    /// Generally will be null if no valid connection is established
     std::unique_ptr<HTTP_LIB_CONNECTION> m_conn;
 
     std::unique_ptr<HTTP_LIB_SETTINGS> m_settings;
@@ -110,9 +112,8 @@ private:
     wxString datasheet_field = "datasheet";
     wxString reference_field = "reference";
 
-     //     category.id       category
+    //     category.id       category
     std::map<std::string, HTTP_LIB_CATEGORY> m_cachedCategories;
-
 };
 
 #endif // SCH_IO_HTTP_LIB_H_
-- 
GitLab