What this plant asks of its ERP link¶
Ten numbers in this MES used to be literals in the source: how many times a confirmation is offered before somebody has to look at it, how long to wait between attempts, which statuses the ERP puts an order in while it is waiting to be made, how long to wait on one request, and when a number the ERP hands back counts as the number that was sent. Each one was a judgment somebody made once against one ERP, and several of them had a comment beside them arguing for the number rather than stating it.
They are this plant's now. They are seeded from [erp] in the plant pack,
owned by the plant's database from then on, and — for nine of the ten —
edited on Orders › Configuration by somebody holding erp.define, with
the value the plant is actually running on beside each one. They follow the
same rule every setting in this product follows:
The literal that was in the source is the shipped default, unchanged. A plant that writes none of these keys behaves exactly as it did.
The keys¶
| Key | Ships | What it decides |
|---|---|---|
max_attempts |
8 |
How many times one confirmation is offered before it is dead and a person decides |
base_backoff_s |
5 |
The wait before the second attempt, in seconds. It doubles after each failure |
max_backoff_s |
3600 |
The longest this plant waits between two attempts. The doubling stops here |
open_statuses |
["Not Started", "In Process"] |
Which statuses this plant's ERP puts an order in while it is waiting to be made |
float_rel_tol |
0.001 |
How far a number the ERP hands back may differ, as a fraction, and still be the same number |
float_abs_tol |
0.01 |
The same agreement as an absolute amount, for numbers near zero |
http_timeout |
30.0 |
How long the ERPNext connector waits on one request, in seconds |
rest_timeout |
10.0 |
The same, for the plain REST connector |
default_order_priority |
50 |
The priority an order arriving with none inherits. Lower is more urgent |
confirmation_seconds_tolerance |
1.0 |
How far machine_seconds may differ from the time the step was open before fsmes erp validate calls the document wrong |
[erp]
mode = "erpnext"
# A plant whose ERPNext bench is across a VPN, takes a maintenance window on
# Sunday mornings, and has added a status of its own.
max_attempts = 24
max_backoff_s = 21600
http_timeout = 120.0
open_statuses = ["Not Started", "In Process", "Material Transferred"]
fsmes pack check reads every one of them offline, and the Configuration
page refuses the same values in the same sentences. It refuses a value that
would leave the thing it decides unable to decide anything — a confirmation
offered no times at all, an empty list of open statuses, a timeout of
nothing — and it refuses nothing else. A plant that gives up after three
attempts because somebody watches the outbox is answering its own question.
Two lists that are one judgment¶
base_backoff_s and max_backoff_s are one judgment written as two numbers:
a first wait longer than the ceiling on a wait makes every attempt the same
distance apart, which is a retry loop with extra words. Either half is
refused when it crosses the other, so raise the ceiling before you raise the
first wait.
What stays the product's, and why¶
The test is decision 0035's: ask what breaks if two plants answer differently.
- The confirmation contract — its field names, its shapes, and the published JSON Schema an ERP team checks files against. A plant that changed one of those would send a document meaning something nobody else means by it.
- What the MES does with a refusal. An ERP that reads a message and says
no is dead at once rather than retried, whatever
max_attemptssays, because retrying sends the identical message and gets the identical answer. - The words in
open_statuses. The list is the plant's; the vocabulary is the ERP's. This MES holds no list of what ERPNext, SAP or Odoo may call a status and does not judge the words — only that each one is a word, that the list says something, and that none of them has a comma in it, because the list travels to the product as a comma-separated setting.
The one that is not edited on the page¶
confirmation_seconds_tolerance is a pack key and a setting, and it is not
a box you type in. It is read by fsmes erp validate, which reads a folder of
files and nothing else — no ERP, no connector, no database. That is the
whole point of that command: a plant's ERP team runs it on a shadow-mode
outbox, often on a laptop that has never had an MES database on it. There is
no session to read a live row through, so a box on the page saying in force
the moment you save it would have been false. Its row on Orders ›
Configuration says what is true instead: it changes when the pack is applied
and the plant restarts.
Two retry policies, not one¶
[uns] has three numbers with these same three names and these same three
values, and they are deliberately separate settings. The namespace broker on
this site and an ERP across a VPN are two systems with two outages: a plant
that widened its ERP retries because the ERP takes a four-hour maintenance
window on Sundays did not mean to widen how long it holds namespace messages.
Editing them¶
Orders › Configuration (/dashboard/config/supply_chain) lists all six
sections with their keys, the value this plant is running on, and whether
that value is the product's default or one the plant set.
- Open Orders › Configuration. Each row's Set to column holds one box per key, with the key's name beside it.
- Type the new value and press Save. There is one Save per row, because the two backoff numbers and the two read-back tolerances are each one judgment written as two numbers.
- It is in force without a restart. The three a service applies —
max_attempts, the two backoffs — anddefault_order_priorityare in force on the very next message. The four a connector applies —open_statuses, the two tolerances and the two timeouts — reach the running sync worker at the start of its next cycle, which isMES_ERP_POLL_SECONDSlater and five seconds by default. Nothing is restarted and no pack is re-applied either way.
You need the erp.define capability, which the built-in Administrator
and Agent roles hold. Without it the page shows you every value and no box.
Every change is written to the audit trail — who, when, what it was and what it became. Undo is typing the old number back. There is no revision history and no approval step here, because nothing in this MES records the timeout that was in force when this confirmation failed: the message stores its attempts and its error, not the policy that produced them.
Why a connector is handed its settings rather than reading them¶
The ERP sync worker keeps every database transaction short and never lets one span an HTTP call, so the ERP being slow cannot hold up the plant floor. An adapter that opened a database session of its own to find out its timeout would be the first thing to break that rule. So the worker reads this plant's policy once per cycle, in a transaction that is closed before anything is sent, and hands it to the connector. A connector published on its own and written against the older port takes no policy at all and keeps the values it was built with, which is exactly what it did before this existed.
What the pack still does, and what it no longer does¶
fsmes pack apply seeds each key the pack carries, once. After that the
database owns it and a later apply leaves it exactly as it is — the same rule
every other kind a pack seeds already keeps. So editing plant.toml and
re-applying does not move a number this plant has already taken ownership of;
fsmes pack status reports the difference. A pack is how a new plant
starts, not how a running one is steered.
Where the value lives¶
A number is read in three layers, in this order:
- the row in this plant's
plant_settingstable — what its administrator or its pack wrote; - the setting the pack compiled into the environment (
MES_ERP_*); - the literal this version of the product ships.
confirmation_seconds_tolerance has only the second and third of those, for
the reason above.
One change to what the MES sends¶
An order arriving from the ERP with no priority now says so: the
ProductionRequest it is read
into carries priority: null rather than 50. Fifty was this MES's own
answer written into the border, so an order that had never carried a priority
and one that carried exactly fifty arrived as the same document. What an
order carrying none inherits is default_order_priority, applied by the MES
when the order is imported — so nothing about a plant that leaves that key
alone changes, and a plant that dispatches on a 1–9 scale can finally say so.