feat(moteur): listes fermées du protocole exposées par le code
OptimizerPlan::kinds() (désormais appliquée par convertirAction) et verdictCodes(), dans l'ordre des contrôles ; SocketScheduler::knownTriggers() (appliquée par rangDeclencheur), knownFallbackCodes(), knownLastErrorCodes() ; OptimizerClient::knownErrorCodes(). Le contrat OpenRPC en régénère ses énumérations. Aucun comportement changé : mêmes listes, mêmes ordres. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fb581218c8
commit
b45d0496c6
@ -200,6 +200,18 @@ bool OptimizerClient::writeToken(const QString &path, const QByteArray &token, Q
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList OptimizerClient::knownErrorCodes()
|
||||
{
|
||||
return {QStringLiteral("invalid-endpoint"), QStringLiteral("token-too-short"),
|
||||
QStringLiteral("connect-failed"), QStringLiteral("closed-during-handshake"),
|
||||
QStringLiteral("connection-lost"), QStringLiteral("handshake-timeout"),
|
||||
QStringLiteral("handshake-refused"), QStringLiteral("invalid-handshake"),
|
||||
QStringLiteral("major-mismatch"), QStringLiteral("line-too-long"),
|
||||
QStringLiteral("invalid-json"), QStringLiteral("missing-id"), QStringLiteral("unknown-id"),
|
||||
QStringLiteral("timeout"), QStringLiteral("rpc-error"), QStringLiteral("invalid-response"),
|
||||
QStringLiteral("disconnected")};
|
||||
}
|
||||
|
||||
int OptimizerClient::tokenLength(const QByteArray &token)
|
||||
{
|
||||
return int(QString::fromUtf8(token).toUcs4().size());
|
||||
|
||||
@ -165,6 +165,14 @@ public:
|
||||
*/
|
||||
static constexpr int kMinTokenChars = 16;
|
||||
|
||||
/*!
|
||||
* \brief Les codes d'erreur que le client peut retenir (\c lastErrorCode()) ou émettre
|
||||
* (\c planFailed(), \c protocolError()).
|
||||
* \return Connexion, handshake, ligne écartée, requête. La suite \c etm-powersync-protocolschema
|
||||
* confronte la liste au code source du client.
|
||||
*/
|
||||
static QStringList knownErrorCodes();
|
||||
|
||||
/*! \brief Longueur d'un token, comparée à \c kMinTokenChars.
|
||||
* \param token Le token, en UTF-8. \return Son nombre de caractères (points de code). */
|
||||
static int tokenLength(const QByteArray &token);
|
||||
|
||||
@ -103,9 +103,7 @@ QString convertirAction(const QVariant &brut, const QHash<QString, const LoadCon
|
||||
}
|
||||
|
||||
const QString kind = a.value(QStringLiteral("kind")).toString();
|
||||
if (!estChaine(a.value(QStringLiteral("kind")))
|
||||
|| (kind != QLatin1String("setpoint") && kind != QLatin1String("state")
|
||||
&& kind != QLatin1String("constraint"))) {
|
||||
if (!estChaine(a.value(QStringLiteral("kind"))) || !OptimizerPlan::kinds().contains(kind)) {
|
||||
*detail = QStringLiteral("%1 : kind « %2 » inconnu").arg(id, kind);
|
||||
return QStringLiteral("unknown-kind");
|
||||
}
|
||||
@ -240,6 +238,44 @@ bool differe(const LoadAction &demande, const LoadAction &applique, const QStrin
|
||||
|
||||
namespace OptimizerPlan {
|
||||
|
||||
QStringList kinds()
|
||||
{
|
||||
return {QStringLiteral("setpoint"), QStringLiteral("state"), QStringLiteral("constraint")};
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Les verdicts de valider(), dans l'ORDRE de ses contrôles : c'est l'ordre dans lequel un plan
|
||||
// fautif se voit attribuer son code, et celui que rejoue tools/etm-powersync-schema-check.
|
||||
struct CodeVerdict { const char *code; Issue issue; };
|
||||
constexpr CodeVerdict kVerdicts[] = {
|
||||
{"abstain", Issue::Abstention}, {"malformed-plan", Issue::Invalide},
|
||||
{"empty-plan", Issue::Abstention}, {"bad-time", Issue::Invalide},
|
||||
{"slots-unordered", Issue::Invalide}, {"malformed-action", Issue::Invalide},
|
||||
{"unknown-load", Issue::Invalide}, {"unknown-kind", Issue::Invalide},
|
||||
{"kind-mismatch", Issue::Invalide}, {"kind-not-announced", Issue::Invalide},
|
||||
{"missing-reason", Issue::Invalide}, {"bad-value", Issue::Invalide},
|
||||
{"duplicate-load", Issue::Invalide}, {"expired", Issue::Expire},
|
||||
{"no-current-slot", Issue::Abstention}, {"incomplete-slot", Issue::Invalide},
|
||||
};
|
||||
}
|
||||
|
||||
QStringList verdictCodes(Issue issue)
|
||||
{
|
||||
QStringList out;
|
||||
for (const CodeVerdict &v : kVerdicts)
|
||||
if (v.issue == issue)
|
||||
out << QString::fromLatin1(v.code);
|
||||
return out;
|
||||
}
|
||||
|
||||
QStringList verdictCodes()
|
||||
{
|
||||
QStringList out;
|
||||
for (const CodeVerdict &v : kVerdicts)
|
||||
out << QString::fromLatin1(v.code);
|
||||
return out;
|
||||
}
|
||||
|
||||
QString assainirTexte(const QVariant &v)
|
||||
{
|
||||
if (!estChaine(v))
|
||||
|
||||
@ -45,6 +45,26 @@ enum class Issue {
|
||||
Invalide //!< Plan refusé en entier, jamais appliqué partiellement — un échec (§7).
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Les \c kind que le validateur RECONNAÎT (§6) — la liste qu'il applique, pas une copie.
|
||||
* \return \c setpoint, \c state, \c constraint. Un kind hors liste est refusé (\c unknown-kind) ;
|
||||
* \c constraint est reconnu mais toujours refusé (\c kind-mismatch) : aucun mécanisme ne le porte
|
||||
* (annexe F). Le contrat OpenRPC en régénère son énumération (\c ActionKind).
|
||||
*/
|
||||
QStringList kinds();
|
||||
|
||||
/*!
|
||||
* \brief Les codes de verdict que \c valider() peut rendre, dans l'ordre de ses contrôles.
|
||||
* \param issue Issue dont on veut les codes.
|
||||
* \return Les codes de cette issue (\c Valide : aucun). Ce sont les noms des règles
|
||||
* \c x-etm-semantic-rules du contrat OpenRPC et des valeurs de \c fallbackCode ; la suite
|
||||
* \c etm-powersync-protocolschema confronte la liste au code source de \c valider().
|
||||
*/
|
||||
QStringList verdictCodes(Issue issue);
|
||||
|
||||
/*! \brief \return Tous les codes de \c verdictCodes(), dans l'ordre des contrôles de \c valider(). */
|
||||
QStringList verdictCodes();
|
||||
|
||||
/*! \brief Une action reçue, convertie. */
|
||||
struct ActionRecue {
|
||||
LoadAction action; //!< Action interne : mécanisme, motif filtré, niveau \c optimizer provisoire.
|
||||
|
||||
@ -11,13 +11,29 @@ namespace {
|
||||
// Rang d'un déclencheur : le plus significatif l'emporte quand plusieurs se cumulent.
|
||||
int rangDeclencheur(const QString &t)
|
||||
{
|
||||
static const QStringList ordre{QStringLiteral("cycle"), QStringLiteral("forecast"),
|
||||
QStringLiteral("config"), QStringLiteral("load-change"),
|
||||
QStringLiteral("intent")};
|
||||
return ordre.indexOf(t);
|
||||
return SocketScheduler::knownTriggers().indexOf(t);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList SocketScheduler::knownTriggers()
|
||||
{
|
||||
return {QStringLiteral("cycle"), QStringLiteral("forecast"), QStringLiteral("config"),
|
||||
QStringLiteral("load-change"), QStringLiteral("intent")};
|
||||
}
|
||||
|
||||
QStringList SocketScheduler::knownFallbackCodes()
|
||||
{
|
||||
using OptimizerPlan::Issue;
|
||||
return QStringList{QStringLiteral("no-plan")} + OptimizerPlan::verdictCodes(Issue::Abstention)
|
||||
+ OptimizerPlan::verdictCodes(Issue::Expire) + OptimizerPlan::verdictCodes(Issue::Invalide)
|
||||
+ QStringList{QStringLiteral("no-shadow-slot")};
|
||||
}
|
||||
|
||||
QStringList SocketScheduler::knownLastErrorCodes()
|
||||
{
|
||||
return OptimizerClient::knownErrorCodes() + OptimizerPlan::verdictCodes(OptimizerPlan::Issue::Invalide);
|
||||
}
|
||||
|
||||
SocketScheduler::SocketScheduler(IScheduler *ombre, OptimizerClient *client, FournisseurFil fil,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
|
||||
@ -92,6 +92,26 @@ public:
|
||||
*/
|
||||
void noterDeclencheur(const QString &trigger);
|
||||
|
||||
/*!
|
||||
* \brief Les valeurs de \c trigger (§5.1), de la moins à la plus significative.
|
||||
* \return \c cycle, \c forecast, \c config, \c load-change, \c intent — l'ordre qu'applique
|
||||
* \c noterDeclencheur(), et l'énumération \c Trigger du contrat OpenRPC.
|
||||
*/
|
||||
static QStringList knownTriggers();
|
||||
|
||||
/*!
|
||||
* \brief Les valeurs de \c fallbackCode publiées par \c NymeaEnergy.GetPlan (INTERFACE.md).
|
||||
* \return \c no-plan, les codes de verdict d'\c OptimizerPlan::valider() (abstention, expiré,
|
||||
* invalide), \c no-shadow-slot.
|
||||
*/
|
||||
static QStringList knownFallbackCodes();
|
||||
|
||||
/*!
|
||||
* \brief Les valeurs de \c lastErrorCode publiées par \c NymeaEnergy.GetOptimizerStatus.
|
||||
* \return \c OptimizerClient::knownErrorCodes() et les codes de plan invalide.
|
||||
*/
|
||||
static QStringList knownLastErrorCodes();
|
||||
|
||||
/*! \brief \return La cause que portera la prochaine requête. */
|
||||
QString declencheurEnAttente() const { return m_declencheur; }
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user