Compare commits

..

8 Commits

Author SHA1 Message Date
Ian Chua
b37e009c24 fix: propagate force push down put_setting 2026-05-29 18:52:00 +08:00
SoftFever
835d8fb3bb Merge branch 'main' into feature/409-resolutions 2026-05-29 17:26:15 +08:00
Ian Chua
5301e2963e remove formatting churn 2026-05-29 14:41:29 +08:00
Ian Chua
4457d6d061 Merge branch 'feature/409-resolutions' of https://github.com/OrcaSlicer/OrcaSlicer into feature/409-resolutions 2026-05-29 12:08:11 +08:00
Ian Chua
d82cb9d338 fix: pass force push flag to start_sync_user_preset 2026-05-29 12:07:35 +08:00
SoftFever
c33f0b5513 Merge branch 'main' into feature/409-resolutions 2026-05-28 23:15:05 +08:00
Ian Chua
9451827e33 fix: silently log other http errors 2026-05-28 18:09:25 +08:00
Ian Chua
2fe0509359 fix: 409 conflicts resolution in notifications 2026-05-28 17:59:44 +08:00
14 changed files with 226 additions and 76 deletions

View File

@@ -1,11 +1,5 @@
set(_eigen_extra_flags "")
if (MSVC)
set(_eigen_extra_flags "-DCMAKE_CXX_FLAGS:STRING=/bigobj")
endif ()
orcaslicer_add_cmake_project(Eigen
URL https://gitlab.com/libeigen/eigen/-/archive/5.0.1/eigen-5.0.1.zip
URL_HASH SHA256=0dbb1f9e3aaad66f352c03227d8c983f6f0b49e0b07e71a7300f4abcc01aee12
CMAKE_ARGS "${_eigen_extra_flags}"
DEPENDS dep_Boost dep_GMP dep_MPFR
)

View File

@@ -124,9 +124,6 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
{
std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> grouped_meshes;
// Orca: Recompute static mesh-group state for this support generation pass.
TreeSupportSettings::zero_top_z_gap = false;
//FIXME this is ugly, it does not belong here.
for (size_t object_id : print_object_ids) {
const PrintObject &print_object = *print.get_object(object_id);
@@ -1607,14 +1604,9 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
if (settings.move) {
increased = relevant_offset;
if (overspeed > 0) {
coord_t safe_movement_distance =
const coord_t safe_movement_distance =
(current_elem.use_min_xy_dist ? config.xy_min_distance : config.xy_distance) +
(std::min(config.z_distance_top_layers, config.z_distance_bottom_layers) > 0 ? config.min_feature_size : 0);
// Orca:
// safe_movement_distance is used as the safe_offset_inc() step, so keep it non-zero
// to preserve branch movement with zero-clearance support settings.
if (safe_movement_distance == 0)
safe_movement_distance = scaled<coord_t>(0.1);
// The difference to ensure that the result not only conforms to wall_restriction, but collision/avoidance is done later.
// The higher last_safe_step_movement_distance comes exactly from the fact that the collision will be subtracted later.
increased = safe_offset_inc(increased, overspeed, volumes.getWallRestriction(support_element_collision_radius(config, parent.state), layer_idx, parent.state.use_min_xy_dist),
@@ -1825,15 +1817,9 @@ static void increase_areas_one_layer(
* layer z-1:dddddxxxxxxxxxx
* For more detailed visualisation see calculateWallRestrictions
*/
coord_t safe_movement_distance =
const coord_t safe_movement_distance =
(elem.use_min_xy_dist ? config.xy_min_distance : config.xy_distance) +
(std::min(config.z_distance_top_layers, config.z_distance_bottom_layers) > 0 ? config.min_feature_size : 0);
// safe_movement_distance is used as a divisor and as the safe_offset_inc() step,
// so keep it non-zero to avoid division by zero and preserve branch movement.
if (safe_movement_distance == 0)
safe_movement_distance = scaled<coord_t>(0.1);
if (ceiled_parent_radius == volumes.ceilRadius(projected_radius_increased, parent.state.use_min_xy_dist) ||
projected_radius_increased < config.increase_radius_until_radius)
// If it is guaranteed possible to increase the radius, the maximum movement speed can be increased, as it is assumed that the maximum movement speed is the one of the slower moving wall

View File

@@ -836,6 +836,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line("enable_tower_interface_cooldown_during_tower",
have_prime_tower && config->opt_bool("enable_tower_interface_features"));
for (auto el : {"wall_filament", "sparse_infill_filament", "solid_infill_filament", "wipe_tower_filament"})
toggle_line(el, !bSEMM);
bool purge_in_primetower = preset_bundle->printers.get_edited_preset().config.opt_bool("purge_in_prime_tower");
for (auto el : {"wipe_tower_rotation_angle", "wipe_tower_cone_angle",

View File

@@ -12,6 +12,7 @@
#include <boost/chrono/duration.hpp>
#include <boost/log/detail/native_typeof.hpp>
#include <libslic3r/Config.hpp>
#include <mutex>
#include <wx/event.h>
// Localization headers: include libslic3r version first so everything in this file
@@ -4812,6 +4813,8 @@ void GUI_App::handle_http_error(unsigned int status, std::string body, const std
wxQueueEvent(this, evt);
}
static std::mutex conflict_ids_mutex;
void GUI_App::on_http_error(wxCommandEvent &evt)
{
int status = evt.GetInt();
@@ -4887,32 +4890,65 @@ void GUI_App::on_http_error(wxCommandEvent &evt)
return;
}
static bool m_is_error_shown = false;
if (status == 409 && provider == ORCA_CLOUD_PROVIDER) {
BOOST_LOG_TRIVIAL(info) << "Http error 409.";
// Parse the conflict body to extract the error code and server profile id
int conflict_code = 0;
json conflict_body;
try {
conflict_body = json::parse(body_str);
if (conflict_body.contains("code"))
conflict_code = conflict_body["code"].get<int>();
} catch (...) {
BOOST_LOG_TRIVIAL(warning) << "Failed to parse 409 conflict body.";
}
std::string conflict_setting_id;
if (conflict_body.contains("server_profile") && conflict_body["server_profile"].contains("id"))
conflict_setting_id = conflict_body["server_profile"]["id"].get<std::string>();
auto* plater = wxGetApp().plater();
if (plater != nullptr && wxGetApp().imgui()->display_initialized()) {
std::string text;
if (conflict_code == -1) {
text = _u8L("Cloud sync conflict: this preset has a newer version in OrcaCloud.\n"
"Pull downloads the cloud copy. Force push overwrites it with your local preset.");
} else {
text = _u8L("Cloud sync conflict: a preset with this name already exists in OrcaCloud.\n"
"Pull downloads the cloud copy. Force push overwrites it with your local preset.");
}
plater->get_notification_manager()->push_orca_sync_conflict_notification(
text,
[this](wxEvtHandler*) {
std::thread([this]() {
if (is_closing() || !m_agent || !preset_bundle)
return;
BOOST_LOG_TRIVIAL(info) << "Pulling Orca Cloud settings to resolve sync conflict.";
restart_sync_user_preset();
}).detach();
return true;
},
[this, conflict_setting_id](wxEvtHandler*) {
MessageDialog
dlg(mainframe,
_L("Force push will overwrite the cloud copy with your local preset changes.\nDo you want to continue?"),
_L("Resolve cloud sync conflict"), wxCENTER | wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
if (dlg.ShowModal() != wxID_YES)
return false;
if (!conflict_setting_id.empty()) {
std::unique_lock lock(conflict_ids_mutex);
m_pending_conflict_setting_ids.push_back(conflict_setting_id);
}
return true;
});
}
return;
}
// Show general error notification for Orca Cloud API failures (not Bambu)
if (provider == ORCA_CLOUD_PROVIDER && status >= 400 && code != HttpErrorVersionLimited) {
wxString msg;
if (!error.empty()) {
msg = wxString::Format(_L("Failed to connect to OrcaCloud.\nPlease check your network connectivity\n(HTTP %u): %s"), status, wxString::FromUTF8(error));
} else {
msg = wxString::Format(_L("Failed to connect to OrcaCloud.\nPlease check your network connectivity\n(HTTP %u)"), status);
}
if (app_config->get_bool("developer_mode")) {
// Use notification manager if ImGui is ready; fall back to wxMessageBox on Linux
// where ImGui may not be initialized until the user switches to the Prepare tab.
if (wxGetApp().plater() != nullptr && wxGetApp().imgui()->display_initialized()) {
wxGetApp()
.plater()
->get_notification_manager()
->push_notification(NotificationType::PlaterError, NotificationManager::NotificationLevel::WarningNotificationLevel,
msg.ToUTF8().data());
}
}
if (!m_is_error_shown) {
m_is_error_shown = true;
wxMessageBox(msg, _L("Cloud Error"), wxOK | wxICON_ERROR, wxGetApp().mainframe);
}
BOOST_LOG_TRIVIAL(warning) << "API call to OrcaCloud failed with status=" << status;
}
}
@@ -6181,13 +6217,14 @@ void GUI_App::load_pending_vendors()
need_add_filaments.clear();
}
void GUI_App::sync_preset(Preset* preset)
void GUI_App::sync_preset(Preset* preset, bool force)
{
int result = -1;
unsigned int http_code = 200;
std::string updated_info;
long long update_time = 0;
// only sync user's preset
if (!m_agent) return;
if (!preset->is_user()) return;
auto setting_id = preset->setting_id;
@@ -6259,9 +6296,9 @@ void GUI_App::sync_preset(Preset* preset)
result = 0;
}
else {
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code);
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code, ORCA_CLOUD_PROVIDER, force);
if (http_code >= 400) {
result = 0;
result = 0;
updated_info = "hold";
BOOST_LOG_TRIVIAL(error) << "[sync_preset] put setting_id = " << setting_id << " failed, http_code = " << http_code;
} else {
@@ -6733,9 +6770,24 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
int total_count = 0;
sync_count = preset_bundle->prints.get_user_presets(preset_bundle, presets_to_sync);
auto sync_with_lock = [this](Preset& preset) {
bool force = false;
{
std::scoped_lock lock(conflict_ids_mutex);
auto it = std::find_if(m_pending_conflict_setting_ids.begin(), m_pending_conflict_setting_ids.end(),
[&preset](const std::string& id) { return id == preset.setting_id; });
if (it != m_pending_conflict_setting_ids.end()) {
force = true;
m_pending_conflict_setting_ids.erase(it);
}
}
sync_preset(&preset, force);
};
if (sync_count > 0) {
for (Preset& preset : presets_to_sync) {
sync_preset(&preset);
sync_with_lock(preset);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
@@ -6744,7 +6796,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
sync_count = preset_bundle->filaments.get_user_presets(preset_bundle, presets_to_sync);
if (sync_count > 0) {
for (Preset& preset : presets_to_sync) {
sync_preset(&preset);
sync_with_lock(preset);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
@@ -6753,7 +6805,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
sync_count = preset_bundle->printers.get_user_presets(preset_bundle, presets_to_sync);
if (sync_count > 0) {
for (Preset& preset : presets_to_sync) {
sync_preset(&preset);
sync_with_lock(preset);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}

View File

@@ -297,6 +297,7 @@ private:
NetworkAgent* m_agent { nullptr };
std::map<std::string, std::string> need_delete_presets; // store setting ids of preset
std::vector<bool> m_create_preset_blocked { false, false, false, false, false, false }; // excceed limit
std::vector<std::string> m_pending_conflict_setting_ids; // setting_id from the most recent 409 conflict
bool m_networking_compatible { false };
bool m_networking_need_update { false };
bool m_networking_cancel_update { false };
@@ -529,7 +530,7 @@ public:
void add_pending_vendor_preset(const std::pair<std::string, std::map<std::string, std::string>>& preset_data);
void load_pending_vendors();
void sync_preset(Preset* preset);
void sync_preset(Preset* preset, bool force = false);
void start_sync_user_preset(bool with_progress_dlg = false);
void stop_sync_user_preset();
void restart_sync_user_preset();

View File

@@ -2382,6 +2382,79 @@ void NotificationManager::SharedProfilesNotification::render_hypertext(ImGuiWrap
(int)(HyperColor.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f))));
}
void NotificationManager::OrcaSyncConflictNotification::init()
{
PopNotification::init();
// Reserve a dedicated action row for the two conflict-resolution links.
m_lines_count = m_lines_count + 1;
}
void NotificationManager::OrcaSyncConflictNotification::render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y)
{
float x_offset = m_left_indentation;
float shift_y = m_line_height;
float starting_y = m_line_height / 2;
int last_end = 0;
std::string line;
for (size_t i = 0; i < m_endlines.size(); i++) {
if (m_text1.size() >= m_endlines[i]) {
line = m_text1.substr(last_end, m_endlines[i] - last_end);
last_end = m_endlines[i];
if (m_text1.size() > m_endlines[i])
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y);
imgui.text(line.c_str());
}
}
const float action_y = starting_y + m_endlines.size() * shift_y;
const std::string pull_text = _u8L("Pull");
render_action_link(imgui, x_offset, action_y, pull_text, "##orca_sync_pull", m_pull_callback);
if (m_force_push_callback) {
const std::string force_push_text = _u8L("Force push");
const float force_x = x_offset + ImGui::CalcTextSize((pull_text + " ").c_str()).x;
render_action_link(imgui, force_x, action_y, force_push_text, "##orca_sync_force_push", m_force_push_callback);
}
}
void NotificationManager::OrcaSyncConflictNotification::render_action_link(ImGuiWrapper& imgui, float text_x, float text_y, const std::string& text,
const char* id, const std::function<bool(wxEvtHandler*)>& callback)
{
ImVec2 part_size = ImGui::CalcTextSize(text.c_str());
ImGui::SetCursorPosX(text_x - 4);
ImGui::SetCursorPosY(text_y - 5);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
if (imgui.button(id, part_size.x + 6, part_size.y + 10)) {
if (callback && callback(m_evt_handler))
close();
}
ImGui::PopStyleColor(3);
ImVec4 color = m_HyperTextColor;
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly))
color = m_HyperTextColorHover;
push_style_color(ImGuiCol_Text, color, m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::SetCursorPosX(text_x);
ImGui::SetCursorPosY(text_y);
imgui.text(text.c_str());
ImGui::PopStyleColor();
ImVec2 lineEnd = ImGui::GetItemRectMax();
lineEnd.y -= 2;
ImVec2 lineStart = lineEnd;
lineStart.x = ImGui::GetItemRectMin().x;
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd,
IM_COL32((int)(color.x * 255), (int)(color.y * 255), (int)(color.z * 255),
(int)(color.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f))));
}
void NotificationManager::push_shared_profiles_notification(const std::string& explore_url)
{
close_notification_of_type(NotificationType::OrcaSharedProfilesAvailable);
@@ -2391,6 +2464,16 @@ void NotificationManager::push_shared_profiles_notification(const std::string& e
push_notification_data(std::make_unique<NotificationManager::SharedProfilesNotification>(data, m_id_provider, m_evt_handler, explore_url), 0);
}
void NotificationManager::push_orca_sync_conflict_notification(const std::string& text,
std::function<bool(wxEvtHandler*)> pull_callback,
std::function<bool(wxEvtHandler*)> force_push_callback)
{
close_notification_of_type(NotificationType::OrcaSyncConflict);
NotificationData data{ NotificationType::OrcaSyncConflict, NotificationLevel::WarningNotificationLevel, 0, text };
push_notification_data(std::make_unique<NotificationManager::OrcaSyncConflictNotification>(
data, m_id_provider, m_evt_handler, std::move(pull_callback), std::move(force_push_callback)), 0);
}
void NotificationManager::push_download_URL_progress_notification(size_t id, const std::string& text, std::function<bool(DownloaderUserAction, int)> user_action_callback)
{
// If already exists

View File

@@ -15,6 +15,8 @@
#include <wx/time.h>
#include <string>
#include <functional>
#include <utility>
#include <vector>
#include <deque>
#include <unordered_set>
@@ -162,6 +164,8 @@ enum class NotificationType
BBLMixUsePLAAndPETG,
BBLNozzleFilamentIncompatible,
OrcaSharedProfilesAvailable,
OrcaCloudAPIError,
OrcaSyncConflict,
NotificationTypeCount
};
@@ -274,6 +278,9 @@ public:
// Shared profiles available for selected printer
void push_shared_profiles_notification(const std::string& explore_url);
void push_orca_sync_conflict_notification(const std::string& text,
std::function<bool(wxEvtHandler*)> pull_callback,
std::function<bool(wxEvtHandler*)> force_push_callback);
// Download URL progress notif
void push_download_URL_progress_notification(size_t id, const std::string& text, std::function<bool(DownloaderUserAction, int)> user_action_callback);
@@ -887,6 +894,30 @@ private:
std::string m_explore_url;
bool m_dont_show_clicked{ false };
};
class OrcaSyncConflictNotification : public PopNotification
{
public:
OrcaSyncConflictNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler,
std::function<bool(wxEvtHandler*)> pull_callback,
std::function<bool(wxEvtHandler*)> force_push_callback)
: PopNotification(n, id_provider, evt_handler)
, m_pull_callback(std::move(pull_callback))
, m_force_push_callback(std::move(force_push_callback))
{
m_multiline = true;
}
protected:
void init() override;
void render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
void render_action_link(ImGuiWrapper& imgui, float text_x, float text_y, const std::string& text,
const char* id, const std::function<bool(wxEvtHandler*)>& callback);
std::function<bool(wxEvtHandler*)> m_pull_callback;
std::function<bool(wxEvtHandler*)> m_force_push_callback;
};
class SlicingProgressNotification;
// in HintNotification.hpp

View File

@@ -433,7 +433,7 @@ std::string BBLCloudServiceAgent::request_setting_id(std::string name, std::map<
return "";
}
int BBLCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code)
int BBLCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force)
{
auto& plugin = BBLNetworkPlugin::instance();
auto agent = plugin.get_agent();

View File

@@ -70,7 +70,7 @@ public:
// Settings Synchronization
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) override;
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force = false) override;
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
int delete_setting(std::string setting_id) override;

View File

@@ -247,7 +247,7 @@ public:
/**
* Update or create a preset with a known setting_id.
*/
virtual int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) = 0;
virtual int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force = false) = 0;
/**
* Trigger bulk download of user presets.

View File

@@ -383,11 +383,12 @@ int NetworkAgent::put_setting(std::string setting_id,
std::string name,
std::map<std::string, std::string>* values_map,
unsigned int* http_code,
const std::string& provider)
const std::string& provider,
bool force)
{
const auto cloud_agent = get_cloud_agent(provider);
if (cloud_agent)
return cloud_agent->put_setting(std::move(setting_id), std::move(name), values_map, http_code);
return cloud_agent->put_setting(std::move(setting_id), std::move(name), values_map, http_code, force);
return -1;
}

View File

@@ -93,7 +93,7 @@ public:
// NOTE: this should always call only OrcaCloud
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets, const std::string& provider = ORCA_CLOUD_PROVIDER);
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, const std::string& provider = ORCA_CLOUD_PROVIDER);
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, const std::string& provider = ORCA_CLOUD_PROVIDER);
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, const std::string& provider = ORCA_CLOUD_PROVIDER, bool force = false);
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr, const std::string& provider = ORCA_CLOUD_PROVIDER);
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr, const std::string& provider = ORCA_CLOUD_PROVIDER);
int delete_setting(std::string setting_id, const std::string& provider = ORCA_CLOUD_PROVIDER);

View File

@@ -56,6 +56,7 @@ constexpr const char* ORCA_DEFAULT_PUB_KEY = "sb_publishable_lvVe_whOi80SU9BPSxM
constexpr const char* ORCA_HEALTH_PATH = "/api/v1/health";
constexpr const char* ORCA_SYNC_PULL_PATH = "/api/v1/sync/pull";
constexpr const char* ORCA_SYNC_PUSH_PATH = "/api/v1/sync/push";
constexpr const char* ORCA_SYNC_FORCE_PUSH_PATH = "/api/v1/sync/force-push";
constexpr const char* ORCA_SYNC_DELETE_PATH = "/api/v1/sync/delete";
constexpr const char* ORCA_PROFILES_PATH = "/api/v1/sync/profiles";
constexpr const char* ORCA_SUBSCRIPTIONS_PATH = "/api/v1/subscriptions";
@@ -965,7 +966,7 @@ std::string OrcaCloudServiceAgent::request_setting_id(std::string name, std::map
return "";
}
int OrcaCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code)
int OrcaCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force)
{
// Extract original_updated_time for Optimistic Concurrency Control
// If present, server will verify version before update. If absent, treated as insert.
@@ -989,7 +990,7 @@ int OrcaCloudServiceAgent::put_setting(std::string setting_id, std::string name,
}
}
auto result = sync_push(setting_id, name, content, original_updated_time);
auto result = sync_push(setting_id, name, content, original_updated_time, force);
if (http_code) *http_code = result.http_code;
if (result.success) {
@@ -1208,11 +1209,11 @@ int OrcaCloudServiceAgent::sync_pull(
}
}
SyncPushResult OrcaCloudServiceAgent::sync_push(
const std::string& profile_id,
const std::string& name,
const nlohmann::json& content,
const std::string& original_updated_time)
SyncPushResult OrcaCloudServiceAgent::sync_push(const std::string& profile_id,
const std::string& name,
const nlohmann::json& content,
const std::string& original_updated_time,
bool force)
{
SyncPushResult result;
result.success = false;
@@ -1243,7 +1244,7 @@ SyncPushResult OrcaCloudServiceAgent::sync_push(
std::string response;
unsigned int http_code = 0;
int http_result = http_post(ORCA_SYNC_PUSH_PATH, body_str, &response, &http_code);
int http_result = http_post(force ? ORCA_SYNC_FORCE_PUSH_PATH : ORCA_SYNC_PUSH_PATH, body_str, &response, &http_code);
result.http_code = http_code;
@@ -1888,7 +1889,7 @@ int OrcaCloudServiceAgent::http_post(const std::string& path, const std::string&
.on_error([&](std::string resp_body, std::string error, unsigned resp_status) {
result.success = false;
result.status = resp_status == 0 ? 404 : resp_status;
result.body = body;
result.body = resp_body;
BOOST_LOG_TRIVIAL(error) << "OrcaCloudServiceAgent: HTTP error - " << error;
})
.timeout_max(30)

View File

@@ -176,7 +176,12 @@ public:
// ========================================================================
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) override;
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code, bool force = false) override;
SyncPushResult sync_push(const std::string& profile_id,
const std::string& name,
const nlohmann::json& content,
const std::string& original_updated_time = "",
bool force = false);
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
int delete_setting(std::string setting_id) override;
@@ -294,13 +299,6 @@ private:
std::function<void(int http_code, const std::string& error)> on_error
);
SyncPushResult sync_push(
const std::string& profile_id,
const std::string& name,
const nlohmann::json& content,
const std::string& original_updated_time = ""
);
// HTTP request helpers
int http_get(const std::string& path, std::string* response_body, unsigned int* http_code);
int http_post(const std::string& path, const std::string& body, std::string* response_body, unsigned int* http_code);