mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 16:50:06 +00:00 
			
		
		
		
	Enable placefile auto-refresh (no more frequent than every 15 seconds)
This commit is contained in:
		
							parent
							
								
									170e30ca6c
								
							
						
					
					
						commit
						80c307c5fc
					
				
					 3 changed files with 125 additions and 11 deletions
				
			
		|  | @ -22,6 +22,7 @@ | ||||||
| #include <boost/json.hpp> | #include <boost/json.hpp> | ||||||
| #include <boost/tokenizer.hpp> | #include <boost/tokenizer.hpp> | ||||||
| #include <cpr/cpr.h> | #include <cpr/cpr.h> | ||||||
|  | #include <fmt/chrono.h> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
|  | @ -85,10 +86,16 @@ public: | ||||||
|    } |    } | ||||||
|    ~PlacefileRecord() |    ~PlacefileRecord() | ||||||
|    { |    { | ||||||
|       std::unique_lock lock(refreshMutex_); |       std::unique_lock refreshLock(refreshMutex_); | ||||||
|  |       std::unique_lock timerLock(timerMutex_); | ||||||
|       refreshTimer_.cancel(); |       refreshTimer_.cancel(); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    bool                 refresh_enabled() const; | ||||||
|  |    std::chrono::seconds refresh_time() const; | ||||||
|  | 
 | ||||||
|  |    void CancelRefresh(); | ||||||
|  |    void ScheduleRefresh(); | ||||||
|    void Update(); |    void Update(); | ||||||
|    void UpdateAsync(); |    void UpdateAsync(); | ||||||
|    void UpdatePlacefile(const std::shared_ptr<gr::Placefile>& placefile); |    void UpdatePlacefile(const std::shared_ptr<gr::Placefile>& placefile); | ||||||
|  | @ -125,6 +132,10 @@ public: | ||||||
|    boost::asio::thread_pool       threadPool_ {1u}; |    boost::asio::thread_pool       threadPool_ {1u}; | ||||||
|    boost::asio::steady_timer      refreshTimer_ {threadPool_}; |    boost::asio::steady_timer      refreshTimer_ {threadPool_}; | ||||||
|    std::mutex                     refreshMutex_ {}; |    std::mutex                     refreshMutex_ {}; | ||||||
|  |    std::mutex                     timerMutex_ {}; | ||||||
|  | 
 | ||||||
|  |    std::string                           lastRadarSite_ {}; | ||||||
|  |    std::chrono::system_clock::time_point lastUpdateTime_ {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) | PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) | ||||||
|  | @ -210,11 +221,26 @@ void PlacefileManager::set_placefile_enabled(const std::string& name, | ||||||
| 
 | 
 | ||||||
|       Q_EMIT PlacefileEnabled(name, enabled); |       Q_EMIT PlacefileEnabled(name, enabled); | ||||||
| 
 | 
 | ||||||
|  |       using namespace std::chrono_literals; | ||||||
|  | 
 | ||||||
|       // Update the placefile
 |       // Update the placefile
 | ||||||
|       // TODO: Only update if it's out of date, or if the radar site has changed
 |  | ||||||
|       if (enabled) |       if (enabled) | ||||||
|       { |       { | ||||||
|          it->second->UpdateAsync(); |          if (p->radarSite_ != nullptr && | ||||||
|  |              record->lastRadarSite_ != p->radarSite_->id()) | ||||||
|  |          { | ||||||
|  |             // If the radar site has changed, update now
 | ||||||
|  |             record->UpdateAsync(); | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             // Otherwise, schedule an update
 | ||||||
|  |             record->ScheduleRefresh(); | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |       else if (!enabled) | ||||||
|  |       { | ||||||
|  |          record->CancelRefresh(); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| } | } | ||||||
|  | @ -262,6 +288,31 @@ void PlacefileManager::set_placefile_url(const std::string& name, | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool PlacefileManager::Impl::PlacefileRecord::refresh_enabled() const | ||||||
|  | { | ||||||
|  |    if (placefile_ != nullptr) | ||||||
|  |    { | ||||||
|  |       using namespace std::chrono_literals; | ||||||
|  |       return placefile_->refresh() > 0s; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::chrono::seconds | ||||||
|  | PlacefileManager::Impl::PlacefileRecord::refresh_time() const | ||||||
|  | { | ||||||
|  |    using namespace std::chrono_literals; | ||||||
|  | 
 | ||||||
|  |    if (refresh_enabled()) | ||||||
|  |    { | ||||||
|  |       // Don't refresh more often than every 15 seconds
 | ||||||
|  |       return std::max(placefile_->refresh(), 15s); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return -1s; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void PlacefileManager::Impl::InitializePlacefileSettings() | void PlacefileManager::Impl::InitializePlacefileSettings() | ||||||
| { | { | ||||||
|    std::string appDataPath { |    std::string appDataPath { | ||||||
|  | @ -407,8 +458,11 @@ void PlacefileManager::AddUrl(const std::string& urlString, | ||||||
| 
 | 
 | ||||||
|    Q_EMIT PlacefileUpdated(normalizedUrl); |    Q_EMIT PlacefileUpdated(normalizedUrl); | ||||||
| 
 | 
 | ||||||
|    // Queue a placefile update
 |    // Queue a placefile update, either if enabled, or if we don't know the title
 | ||||||
|  |    if (enabled || title.empty()) | ||||||
|  |    { | ||||||
|       record->UpdateAsync(); |       record->UpdateAsync(); | ||||||
|  |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileManager::LoadFile(const std::string& filename) | void PlacefileManager::LoadFile(const std::string& filename) | ||||||
|  | @ -491,6 +545,9 @@ void PlacefileManager::Impl::PlacefileRecord::Update() | ||||||
| { | { | ||||||
|    logger_->debug("Update: {}", name_); |    logger_->debug("Update: {}", name_); | ||||||
| 
 | 
 | ||||||
|  |    // Take unique lock before refreshing
 | ||||||
|  |    std::unique_lock lock {refreshMutex_}; | ||||||
|  | 
 | ||||||
|    // Make a copy of name in the event it changes.
 |    // Make a copy of name in the event it changes.
 | ||||||
|    const std::string name {name_}; |    const std::string name {name_}; | ||||||
| 
 | 
 | ||||||
|  | @ -581,15 +638,64 @@ void PlacefileManager::Impl::PlacefileRecord::Update() | ||||||
|          // Update the placefile
 |          // Update the placefile
 | ||||||
|          placefile_      = updatedPlacefile; |          placefile_      = updatedPlacefile; | ||||||
|          title_          = placefile_->title(); |          title_          = placefile_->title(); | ||||||
|  |          lastUpdateTime_ = std::chrono::system_clock::now(); | ||||||
|  | 
 | ||||||
|  |          if (p->radarSite_ != nullptr) | ||||||
|  |          { | ||||||
|  |             lastRadarSite_ = p->radarSite_->id(); | ||||||
|  |          } | ||||||
| 
 | 
 | ||||||
|          // Notify slots of the placefile update
 |          // Notify slots of the placefile update
 | ||||||
|          Q_EMIT p->self_->PlacefileUpdated(name); |          Q_EMIT p->self_->PlacefileUpdated(name); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // TODO: Update refresh timer
 |    // Update refresh timer
 | ||||||
|    // TODO: Can running this function out of sync with an existing refresh timer
 |    ScheduleRefresh(); | ||||||
|    // cause issues?
 | } | ||||||
|  | 
 | ||||||
|  | void PlacefileManager::Impl::PlacefileRecord::ScheduleRefresh() | ||||||
|  | { | ||||||
|  |    using namespace std::chrono_literals; | ||||||
|  | 
 | ||||||
|  |    if (!enabled_ || !refresh_enabled()) | ||||||
|  |    { | ||||||
|  |       // Refresh is disabled
 | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    std::unique_lock lock {timerMutex_}; | ||||||
|  | 
 | ||||||
|  |    auto nextUpdateTime      = lastUpdateTime_ + refresh_time(); | ||||||
|  |    auto timeUntilNextUpdate = nextUpdateTime - std::chrono::system_clock::now(); | ||||||
|  | 
 | ||||||
|  |    logger_->debug( | ||||||
|  |       "Scheduled refresh in {:%M:%S} ({})", | ||||||
|  |       std::chrono::duration_cast<std::chrono::seconds>(timeUntilNextUpdate), | ||||||
|  |       name_); | ||||||
|  | 
 | ||||||
|  |    refreshTimer_.expires_after(timeUntilNextUpdate); | ||||||
|  |    refreshTimer_.async_wait( | ||||||
|  |       [this](const boost::system::error_code& e) | ||||||
|  |       { | ||||||
|  |          if (e == boost::asio::error::operation_aborted) | ||||||
|  |          { | ||||||
|  |             logger_->debug("Refresh timer cancelled"); | ||||||
|  |          } | ||||||
|  |          else if (e != boost::system::errc::success) | ||||||
|  |          { | ||||||
|  |             logger_->warn("Refresh timer error: {}", e.message()); | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             Update(); | ||||||
|  |          } | ||||||
|  |       }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PlacefileManager::Impl::PlacefileRecord::CancelRefresh() | ||||||
|  | { | ||||||
|  |    refreshTimer_.cancel(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileManager::Impl::PlacefileRecord::UpdateAsync() | void PlacefileManager::Impl::PlacefileRecord::UpdateAsync() | ||||||
|  | @ -603,7 +709,8 @@ void PlacefileManager::Impl::PlacefileRecord::UpdatePlacefile( | ||||||
|    // Update placefile
 |    // Update placefile
 | ||||||
|    placefile_ = placefile; |    placefile_ = placefile; | ||||||
| 
 | 
 | ||||||
|    // TODO: Update refresh timer
 |    // Update refresh timer
 | ||||||
|  |    ScheduleRefresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<PlacefileManager> PlacefileManager::Instance() | std::shared_ptr<PlacefileManager> PlacefileManager::Instance() | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <scwx/common/geographic.hpp> | #include <scwx/common/geographic.hpp> | ||||||
| 
 | 
 | ||||||
|  | #include <chrono> | ||||||
| #include <istream> | #include <istream> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <optional> | #include <optional> | ||||||
|  | @ -174,6 +175,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    std::string                                            name() const; |    std::string                                            name() const; | ||||||
|    std::string                                            title() const; |    std::string                                            title() const; | ||||||
|  |    std::chrono::seconds                                   refresh() const; | ||||||
|    std::unordered_map<std::size_t, std::shared_ptr<Font>> fonts(); |    std::unordered_map<std::size_t, std::shared_ptr<Font>> fonts(); | ||||||
|    std::shared_ptr<Font>                                  font(std::size_t i); |    std::shared_ptr<Font>                                  font(std::size_t i); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -113,6 +113,11 @@ std::string Placefile::title() const | ||||||
|    return p->title_; |    return p->title_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::chrono::seconds Placefile::refresh() const | ||||||
|  | { | ||||||
|  |    return p->refresh_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::unordered_map<std::size_t, std::shared_ptr<Placefile::Font>> | std::unordered_map<std::size_t, std::shared_ptr<Placefile::Font>> | ||||||
| Placefile::fonts() | Placefile::fonts() | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat