AWS SNS filtered subscription with exists = false for messages without attributes set - amazon-web-services

I am setting up subscriptions to a topic that a number of different apps publish to. I want to filter the subscription of one particular app so that it doesn't receive back messages that it sends.
I tried adding an attribute with a value identifying the app, eg x-forwarded-by=myapp and set the filter policy as:
{
"x-forwarded-by": [{"anything-but": ["myapp"]}]
}
That correctly prevented the app receiving these however it also didn't receive any messages where there was no x-forwarded-by attribute, nor did it receive any messages whether there were either no attributes or there was an empty attribute object, eg, I would have expected to see messages with:
"MessageAttributes": null
"MessageAttributes": {}
"MessageAttributes": {"someOtherAttribute":{"DataType":"string", "StringValue": "SomeValue"}}
I also tried using an exists filter so that if the app set that attribute, it could filter it out later, eg:
{
"x-forwarded-by-my-app": [{"exists":false}]
}
This only worked if there was at least one other attribute set, and this would require me updating every app that publishes to include a dummy attribute.
I tried combining them, as in:
{
"x-forwarded-by": [
{"exists":false},
{"anything-but":["myapp"]}
}
And this worked slightly better as it handled the case of the x-forwarded-by header either not being present or having a different value. It doesn't however handle the case of no attributes being set.
Is there a way to achieve this with a filtered subscription or do I have to just have the app receive these notifications and have the app check for and ignore them?

It seems there is some issue with "anything-but", I tried this with { {"exists":false},"anything-but":["myapp", ""]} and it works.
In my case I went ahead with: {{"exists":false},"positiveCase"}.

Related

AWS IoT: When to use thing attribute over Shadow

I saw that there was an question already, but I receive a page not found error when accessing it: https://stackoverflow.com/questions/57284026/aws-iot-thing-attrubite-vs-shadow-property?S_TACT=
So I've got the same question.
I've got some fields which could definitely be an attribute as they're not changing: DeviceId, SerialNumber and some others.
But I also want to store/update :
rather seldomly updated fields: e.g. the status from (Created -> Registered -> Unregistered)
frequently updated fields: e.g. lastSeen timestamp when the last message was sent
Should I now use Device Shadow for everything, Thing Attributes for everything or mix it?

Can't access SQS message attributes using boto3

I'm trying to pass and then retrieve a message with attributes into AWS SQS.
Even though I can see attributes of a message through Management Console, I can't get them using boto3, always get None. Changing "AttributeNames" doesn't make a difference. Message body can be retrieved OK.
import boto3
sqs = boto3.resource('sqs', region_name = "us-west-2")
queue = sqs.get_queue_by_name(QueueName='test')
queue.send_message(MessageBody = "LastEvaluatedKey",
MessageAttributes ={
'class_number':{
"StringValue":"Value value ",
"DataType":"String"
}
}
)
messages = queue.receive_messages(
MaxNumberOfMessages=1,
AttributeNames=['All']
)
for msg in messages:
print(msg.message_attributes) # returns None
print(msg.body) # returns correct value
Attributes (system generated) and Message Attributes (user defined) are two different kinds of things provided by the back-end API.
You're looking for message attributes, but you're asking the code to fetch attributes, instead.
AttributeNames=['All']`
It seems like you need to be fetching message attributes...
MessageAttributeNames=['All']
...when calling queue.receive_messages(). Or, the specific message attribute names that you want, if known, could be used instead of 'All' (which -- had I designed this API -- would have been called '*', but I digress).
Admittedly, this is only an intuitive guess on my part based on familiarity with the underlying API, but it seems to be consistent with http://boto3.readthedocs.io/en/latest/guide/sqs.html.

loopback operation hook: add filter to count api

I need to intercept my loopback queries before they query my Mongodb to add additional filters, for example, to limit the object to what the user has access to.
I can successfully update the query on access operation hook to add filters to the GET /Applications , where Applications is my object. However This fails to work for GET /Applications/count
The command runs with a 200, however it returns zero results, even though I'm adding the exact same filters. There most be something different about count that I'm missing. The ctx object looks have a ton of functions/objects in it. I'm only touching the query property, but there must be something else I need to do.
Any ideas? Thank you, Dan
Could you please share your access hook observer's implementation. I tried it on a sample app, and following access hook works as expected for /api/Books/count:
module.exports = function(Book) {
Book.observe('access', function logQuery(ctx, next) {
ctx.query.where.id = 2; // changing filter value for where
console.log('Accessing %s matching %j', ctx.Model.modelName, ctx.query.where);
next();
});
};
Verify that you're modifying query property of Context (see access hook).
Hope that helps.

How to get all goals triggered during Sitecore session in commitDataSet Analytics pipeline?

I have an Analytics pipeline added just before the standard one in section to delete duplicate triggered pageevents before submitting all to database so I can have unique triggered events as there seems to be a bug on android/ios devices that triggers several events within few seconds interval.
In this custom pipeline I need to get the list of all goals/events the current user triggered in his session so I can compare with the values in dataset obtained from args parameter and delete the ones already triggered.
The args.DataSet.Tables["PageEvents"] only returns the set to be submitted to database and that doesn't help since it is changing each time this pipeline runs. I also tried Sitecore.Analytics.Tracker.Visitor.DataSet but I get a null value for these properties.
Does anyone knows a way how to get a list with all goals the user triggered so far in his session without requesting it directly to the database ?
Some code:
public class CommitUniqueAnalytics : CommitDataSetProcessor
{
public override void Process(CommitDataSetArgs args)
{
Assert.ArgumentNotNull(args, "args");
var table = args.DataSet.Tables["PageEvents"];
if (table != null)
{
//Sitecore.Analytics.Tracker.Visitor.DataSet.PageEvents - this list always empty
...........
}
}
}
I had a similar question.
In Sitecore 7.5 I found that this worked:
Tracker.Current.Session.Interaction.Pages.SelectMany(x=>x.PageEvents)
However I'm a little worried that this will be inefficient if the Pages collection is very large.

Microsoft Dynamics CRM - Pass Parameters from Web Service to IPlugins

We are building some plugins in Microsoft Dynamics CRM by inheriting from IPlugin. We have these configured so they fire whenever an Account is updated.
The problem is the plugins are calling our services, which causes our service to respond with an update. We are doing some pretty hacky things right now to prevent these cyclical updates from happening.
We were wondering if there was a way to pass a value to the IOrganizationService service (the web service) that a plugin can look at. Our other system could send a flag ("hey, don't bothing sending an update!") and the plugin could skip calling back.
Can we pass parameters from web service to the plugins?
Good idea could be usage of custom flag-field. For example you add bit field and call it CallFromExternalSystem. So when you make an update from your external system through IOranizationService you just fill this flag with true field and in plugin you can check condition that this field is present in fields list so you have no need to call external system endpoint again.
We decided the correct solution was to use the value found in IPluginExecutionContext.InputParameters["Target"]. In the case of an Update, this returns an Entity containing attributes for all the attributes that were updated.
We basically have a list of attribute names we cared about. We loop through names and see if any of them appear in the entity attribute list. If so, we send an update to our other system. The good news is, Dynamics CRM ignores updates where the values don't actually change, so trying to update a value to itself is no-op.
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext));
Entity entity = (Entity)context.InputParameters["Target"];
string[] fields = new string[] { "name", "statecode", "address1_line1" };
bool hasUpdates = fields.Where(f => entity.Attributes.Contains(f)).Any();
if (!hasUpdates)
{
return;
}
}