Skip to content

Commit

Permalink
FIX correctly identify changes in JSON attribute values in subscripti…
Browse files Browse the repository at this point in the history
…on triggering logic
  • Loading branch information
fgalan committed Nov 8, 2023
1 parent 9639bc4 commit 1520c7e
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 49 deletions.
71 changes: 36 additions & 35 deletions src/lib/mongoBackend/MongoCommonUpdate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,48 +529,49 @@ static ChangeType mergeAttrInfo
/* Was it an actual update? */
ChangeType changeType = NO_CHANGE;

/* We consider there is a change in the value if one or more of the following are true:
*
* 1) the value of the attribute changed (see attrValueChanges or CompoundValueNode::equal() for details)
* 2) the type of the attribute changed (in this case, !attr.hasField(ENT_ATTRS_TYPE) is needed, as attribute
* type is optional according to NGSI and the attribute may not have that field in the BSON)
*
* In addition, we consider there is change in the metadata if:
*
* 3) the metadata changed (this is done checking if the size of the original and final metadata vectors is
* different and, if they are of the same size, checking if the vectors are not equal)
*/
bool valueChanged;
bool typeChanged;
bool mdChanged;
if (caP->compoundValueP == NULL)
{
/* In the case of simple value, we consider there is a change in the value if one or more of the following are true:
*
* 1) the value of the attribute changed (see attrValueChanges for details)
* 2) the type of the attribute changed (in this case, !attr.hasField(ENT_ATTRS_TYPE) is needed, as attribute
* type is optional according to NGSI and the attribute may not have that field in the BSON)
*
* In addition, we consider there is change in the metadata if:
*
* 3) the metadata changed (this is done checking if the size of the original and final metadata vectors is
* different and, if they are of the same size, checking if the vectors are not equal)
*/
bool valueChanged = attrValueChanges(attr, caP, forcedUpdate, apiVersion) ||
((!caP->type.empty()) && (!attr.hasField(ENT_ATTRS_TYPE) || getStringFieldF(attr, ENT_ATTRS_TYPE) != caP->type) );
bool mdChanged = (mdNew.nFields() != mdSize || !equalMetadata(md, mdNew));

if (valueChanged && !mdChanged)
{
changeType = CHANGE_ONLY_VALUE;
}
else if (!valueChanged && mdChanged)
{
changeType = CHANGE_ONLY_MD;
}
else if (valueChanged && mdChanged)
{
changeType = CHANGE_VALUE_AND_MD;
}
else // !valueChanged && !mdChanged
{
changeType = NO_CHANGE;
}
valueChanged = attrValueChanges(attr, caP, forcedUpdate, apiVersion);
}
else
{
// FIXME #643 P6: in the case of compound value, it's more difficult to know if an attribute
// has really changed its value (many levels have to be traversed). Until we can develop the
// matching logic, we consider CHANGE_VALUE_AND_MD always.
//
valueChanged = !caP->compoundValueP->equal(getFieldF(attr, ENT_ATTRS_VALUE));
}
typeChanged = ((!caP->type.empty()) && (!attr.hasField(ENT_ATTRS_TYPE) || getStringFieldF(attr, ENT_ATTRS_TYPE) != caP->type));
mdChanged = (mdNew.nFields() != mdSize || !equalMetadata(md, mdNew));

valueChanged = valueChanged || typeChanged;

if (valueChanged && !mdChanged)
{
changeType = CHANGE_ONLY_VALUE;
}
else if (!valueChanged && mdChanged)
{
changeType = CHANGE_ONLY_MD;
}
else if (valueChanged && mdChanged)
{
changeType = CHANGE_VALUE_AND_MD;
}
else // !valueChanged && !mdChanged
{
changeType = NO_CHANGE;
}

/* 5. Add modification date (actual change only if actual update) */
if (changeType)
Expand Down
18 changes: 17 additions & 1 deletion src/lib/parse/CompoundValueNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ bool CompoundValueNode::equal(const orion::BSONElement& be)
{
// Note object cannot be declared inside switch block
std::vector<orion::BSONElement> ba;
orion::BSONObj bo;

switch (valueType)
{
Expand Down Expand Up @@ -575,7 +576,22 @@ bool CompoundValueNode::equal(const orion::BSONElement& be)
{
return false;
}
// TBD
bo = be.embeddedObject();
if ((int) childV.size() != bo.nFields())
{
return false;
}
for (unsigned int ix = 0; ix < childV.size(); ix++)
{
if (!bo.hasField(childV[ix]->name))
{
return false;
}
if (!(childV[ix]->equal(getFieldF(bo, childV[ix]->name))))
{
return false;
}
}
return true;

case orion::ValueTypeNotGiven:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ echo
echo


echo "05. Dump accumulator, see 3 notifications"
echo "05. Dump accumulator, see 2 notifications"
echo "========================================="
accumulatorDump
echo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ accumulatorStart --pretty-print
# 01. Create subscription covering E-A
# 02. Create E-A entity with JSON object (notification)
# 03. Update E-A entity with same JSON object (no notification)
# 04. Update E-A entity with JSON array (notification)
# 05. Update E-A entity with same JSON array (no notification)
# 06. Update E-A entity with same string (notification)
# 07. Dump accumulator, see 3 notifications
# 04. Update E-A entity with different JSON object (notification)
# 05. Update E-A entity with JSON array (notification)
# 06. Update E-A entity with same JSON array (no notification)
# 07. Update E-A entity with different JSON array (notification)
# 08. Update E-A entity with same string (notification)
# 09. Dump accumulator, see 5 notifications
#

echo "01. Create subscription covering E-A"
Expand Down Expand Up @@ -130,7 +132,40 @@ echo
echo


echo "04. Update E-A entity with JSON array (notification)"
echo "04. Update E-A entity with different JSON object (notification)"
echo "==============================================================="
payload='{
"A": {
"value": {
"text": "foo",
"number": 10,
"bool": true,
"null": null,
"array": [
"22",
{
"x" : [ "x1", "x2" ],
"y" : 3
},
[ "z1", "z2" ]
],
"object": {
"x": {
"x1": "a",
"x2": "b"
},
"y": [ "y1", "y_new" ]
}
},
"type": "Json"
}
}'
orionCurl --url /v2/entities/E/attrs --payload "$payload"
echo
echo


echo "05. Update E-A entity with JSON array (notification)"
echo "===================================================="
payload='{
"A": {
Expand All @@ -150,7 +185,7 @@ echo
echo


echo "05. Update E-A entity with same JSON array (no notification)"
echo "06. Update E-A entity with same JSON array (no notification)"
echo "============================================================"
payload='{
"A": {
Expand All @@ -170,7 +205,27 @@ echo
echo


echo "06. Update E-A entity with same string (notification)"
echo "07. Update E-A entity with different JSON array (notification)"
echo "=============================================================="
payload='{
"A": {
"value": [
"",
{
"x": [ "x1", "x_new" ],
"y": "3"
},
[ "z1", "z2" ]
],
"type": "Array"
}
}'
orionCurl --url /v2/entities/E/attrs --payload "$payload"
echo
echo


echo "08. Update E-A entity with same string (notification)"
echo "====================================================="
payload='{
"A": {
Expand All @@ -183,7 +238,7 @@ echo
echo


echo "07. Dump accumulator, see 3 notifications"
echo "09. Dump accumulator, see 5 notifications"
echo "========================================="
accumulatorDump
echo
Expand Down Expand Up @@ -219,31 +274,47 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36})



04. Update E-A entity with JSON array (notification)
04. Update E-A entity with different JSON object (notification)
===============================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



05. Update E-A entity with JSON array (notification)
====================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



05. Update E-A entity with same JSON array (no notification)
06. Update E-A entity with same JSON array (no notification)
============================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



06. Update E-A entity with same string (notification)
07. Update E-A entity with different JSON array (notification)
==============================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



08. Update E-A entity with same string (notification)
=====================================================
HTTP/1.1 204 No Content
Date: REGEX(.*)
Fiware-Correlator: REGEX([0-9a-f\-]{36})



07. Dump accumulator, see 3 notifications
09. Dump accumulator, see 5 notifications
=========================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Expand Down Expand Up @@ -301,6 +372,60 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}); cbnotif=1
=======================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Content-Length: 274
User-Agent: orion/REGEX(\d+\.\d+\.\d+.*)
Ngsiv2-Attrsformat: normalized
Host: 127.0.0.1:REGEX(\d+)
Accept: application/json
Content-Type: application/json; charset=utf-8
Fiware-Correlator: REGEX([0-9a-f\-]{36}); cbnotif=1

{
"data": [
{
"A": {
"metadata": {},
"type": "Json",
"value": {
"array": [
"22",
{
"x": [
"x1",
"x2"
],
"y": 3
},
[
"z1",
"z2"
]
],
"bool": true,
"null": null,
"number": 10,
"object": {
"x": {
"x1": "a",
"x2": "b"
},
"y": [
"y1",
"y_new"
]
},
"text": "foo"
}
},
"id": "E",
"type": "T"
}
],
"subscriptionId": "REGEX([0-9a-f]{24})"
}
=======================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Content-Length: 162
User-Agent: orion/REGEX(\d+\.\d+\.\d+.*)
Ngsiv2-Attrsformat: normalized
Expand Down Expand Up @@ -339,6 +464,44 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}); cbnotif=1
=======================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Content-Length: 165
User-Agent: orion/REGEX(\d+\.\d+\.\d+.*)
Ngsiv2-Attrsformat: normalized
Host: 127.0.0.1:REGEX(\d+)
Accept: application/json
Content-Type: application/json; charset=utf-8
Fiware-Correlator: REGEX([0-9a-f\-]{36}); cbnotif=1

{
"data": [
{
"A": {
"metadata": {},
"type": "Array",
"value": [
"",
{
"x": [
"x1",
"x_new"
],
"y": "3"
},
[
"z1",
"z2"
]
]
},
"id": "E",
"type": "T"
}
],
"subscriptionId": "REGEX([0-9a-f]{24})"
}
=======================================
POST http://127.0.0.1:REGEX(\d+)/notify
Fiware-Servicepath: /
Content-Length: 124
User-Agent: orion/REGEX(\d+\.\d+\.\d+.*)
Ngsiv2-Attrsformat: normalized
Expand Down

0 comments on commit 1520c7e

Please sign in to comment.