{"id":24,"date":"2026-09-16T10:28:32","date_gmt":"2026-09-16T10:28:32","guid":{"rendered":"https:\/\/docs.latw.ai\/uncategorized\/synchronization-and-log\/"},"modified":"2026-09-16T10:28:32","modified_gmt":"2026-09-16T10:28:32","slug":"synchronization-and-log","status":"publish","type":"post","link":"https:\/\/docs.latw.ai\/pl\/esti-to-wordpress\/synchronization-and-log\/","title":{"rendered":"Synchronization and Log"},"content":{"rendered":"<h1>Synchronization and the sync log<\/h1>\n<h2>How a run works<\/h2>\n<p>A synchronization is not one long request. It is a chain of background steps, which is what keeps a large catalogue from<br \/>\ntiming out:<\/p>\n<ol>\n<li>The <strong>agent directory<\/strong> is refreshed (names, photos, roles, offices).<\/li>\n<li>The <strong>value dictionary<\/strong> is refreshed (the labels behind Esti&#8217;s numeric codes).<\/li>\n<li>Offers are fetched <strong>100 per page<\/strong>. Each page is imported, then the next page is scheduled <strong>30 seconds later<\/strong>.<\/li>\n<li>After the <strong>last<\/strong> page, cleanup runs: offers Esti no longer publishes are deleted.<\/li>\n<\/ol>\n<p>For roughly 600 offers that means around 6 pages and a few minutes end to end. Nothing on the site is blocked while it<br \/>\nhappens.<\/p>\n<p>Runs start:<\/p>\n<ul>\n<li><strong>automatically every 6 hours<\/strong>, through WP-Cron, and<\/li>\n<li><strong>manually<\/strong>, with the <strong>Sync now<\/strong> button on the settings screen.<\/li>\n<\/ul>\n<p>Both need an active license key. Without one the scheduled run returns immediately without contacting Esti, and <strong>Sync<br \/>\nnow<\/strong> is disabled \u2014 see <a href=\"\/esti-to-wordpress\/settings#license\">License<\/a>.<\/p>\n<h2>What one page does with an offer<\/h2>\n<p>For every offer that passes the <a href=\"\/esti-to-wordpress\/settings#import-filter\">import filter<\/a>:<\/p>\n<ul>\n<li><strong>New offer<\/strong> \u2192 a post is created.<\/li>\n<li><strong>Known offer, unchanged<\/strong> \u2192 nothing is written. The plugin compares a fingerprint of the payload, so an untouched<br \/>\ncatalogue costs almost nothing.<\/li>\n<li><strong>Known offer, changed<\/strong> \u2192 the post&#8217;s title, description and all fields are overwritten. <strong>The URL is deliberately not<br \/>\nchanged<\/strong>, so a price change never moves the offer to a new address.<\/li>\n<li><strong>Offer that fails the filter, is inactive, or is not cleared for export<\/strong> \u2192 skipped.<\/li>\n<\/ul>\n<h2>Cleanup and deletion<\/h2>\n<p>Cleanup runs <strong>only after the last page of a run<\/strong>, and only when every page succeeded.<\/p>\n<p>Offers that were not seen anywhere in the run are permanently deleted \u2014 they do not go to the Trash. That covers offers<br \/>\nsold, archived, unpublished in Esti, or excluded by a tightened import filter.<\/p>\n<p>Two safety rules matter here:<\/p>\n<ul>\n<li><strong>A failed page cancels cleanup.<\/strong> If Esti stops answering halfway through, the run is marked failed and nothing is<br \/>\ndeleted. Stale offers are better than an emptied catalogue.<\/li>\n<li><strong>Lost run state deletes nothing.<\/strong> If the record of what the run has seen goes missing, the plugin refuses to<br \/>\nconclude that Esti published nothing, logs a warning and leaves every offer in place.<\/li>\n<\/ul>\n<h2>The Sync log screen<\/h2>\n<p><strong>Esti To WordPress \u2192 Sync log<\/strong> keeps the <strong>last 20 runs<\/strong>, newest first, with up to 200 recorded events each.<\/p>\n<p>For every run the table shows when it started, what triggered it (schedule or manual), how long it took, a status badge<br \/>\nand a one-line result. Clicking a run opens its details: the counters and the full event list.<\/p>\n<h3>Status badges<\/h3>\n<table>\n<thead>\n<tr>\n<th>Badge<\/th>\n<th>Meaning<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>In progress<\/strong><\/td>\n<td>The run is still importing pages. Normal for the first minutes.<\/td>\n<\/tr>\n<tr>\n<td><strong>Finished<\/strong><\/td>\n<td>Every page was imported and cleanup completed.<\/td>\n<\/tr>\n<tr>\n<td><strong>Finished with errors<\/strong><\/td>\n<td>The run completed, but individual offers could not be saved. Open the run to see which.<\/td>\n<\/tr>\n<tr>\n<td><strong>Failed<\/strong><\/td>\n<td>A page could not be fetched from Esti. Nothing was deleted.<\/td>\n<\/tr>\n<tr>\n<td><strong>Interrupted<\/strong><\/td>\n<td>The background chain stopped without reporting. A run that says nothing for <strong>30 minutes<\/strong> is marked this way, and so is a run still open when the next one starts.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Counters<\/h3>\n<table>\n<thead>\n<tr>\n<th>Counter<\/th>\n<th>What it means<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Pages processed<\/td>\n<td>Pages of 100 offers fetched from Esti<\/td>\n<\/tr>\n<tr>\n<td>Offers received<\/td>\n<td>Offers in the payload, against the catalogue total Esti reports<\/td>\n<\/tr>\n<tr>\n<td>New<\/td>\n<td>Offers imported for the first time<\/td>\n<\/tr>\n<tr>\n<td>Updated<\/td>\n<td>Existing offers whose data changed<\/td>\n<\/tr>\n<tr>\n<td>Unchanged<\/td>\n<td>Offers identical to what is already stored<\/td>\n<\/tr>\n<tr>\n<td>Skipped<\/td>\n<td>Inactive, not cleared for export, or excluded by the import filter<\/td>\n<\/tr>\n<tr>\n<td>Removed<\/td>\n<td>Offers deleted because Esti no longer publishes them<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Clear log<\/strong> empties the history. It only deletes the log records, never offers.<\/p>\n<h2>Reading common outcomes<\/h2>\n<p><strong>&#8220;In progress&#8221; for a long time.<\/strong> Normal for the first minutes of a large import. If it stays that way and eventually<br \/>\nflips to <strong>Interrupted<\/strong>, the background chain is not firing \u2014 see WP-Cron below.<\/p>\n<p><strong>Failed, with an HTTP or connection message.<\/strong> Esti did not answer, or answered with an error. Check the company<br \/>\nidentifier and token, then press <strong>Sync now<\/strong> again. Existing offers are untouched.<\/p>\n<p><strong>Finished with errors.<\/strong> The catalogue is fine, but some offers could not be saved. The run details name the Esti offer<br \/>\nIDs and the reason.<\/p>\n<p><strong>&#8220;The agent directory could not be refreshed.&#8221;<\/strong> A warning, not a failure. The previous directory is kept and the offer<br \/>\nimport continues.<\/p>\n<p><strong>&#8220;The value dictionary came back empty.&#8221;<\/strong> Also a warning. Attributes that arrive as numeric codes \u2014 heating, fencing,<br \/>\nownership \u2014 stay hidden on the offer page until a later run brings the dictionary back.<\/p>\n<h2>When the schedule does not fire<\/h2>\n<p>WordPress runs scheduled events on visitor traffic. On a site with very few visitors runs can be late or, if WP-Cron is<br \/>\ndisabled outright, never fire \u2014 which shows up as runs stuck <strong>In progress<\/strong> and then <strong>Interrupted<\/strong>.<\/p>\n<p>Two fixes, both for whoever administers the server:<\/p>\n<ul>\n<li>Trigger <code>wp-cron.php<\/code> from a real system cron every few minutes.<\/li>\n<li>Or run the synchronization from the command line with WP-CLI:<\/li>\n<\/ul>\n<pre><code>wp cron event run osfec_sync_start<\/code><\/pre>\n<p>The manual <strong>Sync now<\/strong> button also depends on the background chain for pages after the first, so a broken WP-Cron shows<br \/>\nup there too: the first page imports, the rest never follow.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Synchronization and the sync log How a run works A synchronization is not one long request. It is a chain of background steps, which is what\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_latwm_translated_slug":"","footnotes":""},"categories":[2],"tags":[],"class_list":["post-24","post","type-post","status-publish","format-standard","hentry","category-esti-to-wordpress"],"_links":{"self":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/24","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/comments?post=24"}],"version-history":[{"count":1,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/24\/revisions"}],"predecessor-version":[{"id":46,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/24\/revisions\/46"}],"wp:attachment":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/media?parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/categories?post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/tags?post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}