POCO-Liberaries:: Poco Key expiry time not working in set method - poco-libraries

I am using Poco Redis Database that stores Key value pair using set command.
my requirement is to delete the entry after 7 days automatically.
i am using poco redis set command to achieve the functionality.
below is the signature for the set command :-
Command Command::set(const std::string& key, const std::string& value, bool overwrite, const Poco::Timespan& expireTime, bool create)
i am Following below procedure:-
first i am connecting to redis data base.
after successful connection, i am creating timespan object with 60 second value and passing key, value and timespan value to set method.
Timespan ts(60,0);
Command setCommand = Command::set(str_metadatakey, str_metadatavalue,true,ts,true);
std::string result = m_oRedisClient.execute(setCommand);
but when i am executing above code it is throwing exception.

Faced same problem.
Exception was "ERR Protocol error: expected '$', got ':'" - as redis expected "expire" to be string.
As a workaround you can explicitly specify expire as string:
Command setCommand = Command::set(key, value);
setCommand << "EX" << "1500"

Related

Send tombstone to compacted topic with kafkaTemplate

I have a compacted topic and I try to send null value (tombstone) with kafkaTemplate, but getting an exception
Unsupported Avro type. Supported types are null, Boolean, Integer, Long, Float, Double, String, byte[] and IndexedRecord
Here is my sending call
kafkaTemplate.send(topic, GenericMessage<KafkaNull>(KafkaNull.INSTANCE))
and part of kafkaTemplate configuration
#Bean
fun kafkaTemplate(producerFactory: ProducerFactory<String, Any>) =
KafkaTemplate(producerFactory)
According to spring docs I have to use KafkaNull as a null-value.
How to send it without any exceptions ?
The problem was with producer factory configuration.
There was
ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to KafkaAvroSerializer::class.java
and I added new producer factory with
ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java
so there is tombstone sending code
stringKafkaTemplate.send(internalTopic, key, null)

Replacing System.Web.Security.MachineKey.Encode with System.Web.Security.MachineKey.Protect

I just upgraded a project from .NET 4.0 to .NET 4.5.1 which produced the following warning:
Public Shared Function Encode(data() As Byte, protectionOption As
System.Web.Security.MachineKeyProtection) As String' is obsolete:
'This method is obsolete and is only provided for compatibility with
existing code. It is recommended that new code use the Protect and
Unprotect methods instead.'
I have lots of values floating around in cookies and emails that were encrypted with Encode. If I am going to replace Encode/Decode with Protect/Unprotect, I still need to be able to decrypt those old encrypted values. Is it possible to Unprotect a value that was encrypted with Encode?
In .NET 4.0 you can use MachineKey API to Protect/Unprotect data like this:
string Protect(byte[] data)
{
if (data == null || data.Length == 0) return null;
return MachineKey.Encode(data, MachineKeyProtection.All);
}
byte[] Unprotect(string value)
{
if (String.IsNullOrWhiteSpace(value)) return null;
return MachineKey.Decode(value, MachineKeyProtection.All);
}
MachineKey.Encode accepts a byte[] to protect and returns a string. The second parameter is an enum that indicates if you want encryption, validation or both. I’d typically suggest both (MachineKeyProtection.All). The returned string can then be used to pass back to the client as a cookie value or a query string value without concern for viewing or tampering. MachineKey.Decode simply reverses the process.
And here’s the 4.5 usage:
string Protect(byte[] data)
{
if (data == null || data.Length == 0) return null;
var value = MachineKey.Protect(data, "");
return Convert.ToBase64String(value);
}
byte[] Unprotect(string value)
{
if (String.IsNullOrWhiteSpace(value)) return null;
var bytes = Convert.FromBase64String(value);
return MachineKey.Unprotect(bytes, "");
}
In 4.5 the old APIs are deprecated in favor of these new Protect and Unprotect APIs. The new APIs no longer accept the level of protection (they always encrypt and MAC now [which is good]) and instead now accept a new parameter which is called purpose. This purpose parameter is intended to act somewhat as a validation mechanism. If we use a value that’s specific to the user (as we do above with the GetMachineKeyPurpose helper) we then are verifying that the value can only be unprotected by the same user. This is a nice addition in 4.5.
No - the process is different. Not to mention you'll be trying to Unprotect data that has no additional parameter specified (which won't work) and sometimes decoding data with the additional parameter specified (if you are ideally taking advantage of how protect works)
I'd refactor the code to be able to tell when the old data is present and write a new cookie/etc out using Protect();
On the first case I mentioned - you cannot use a blank parameter in Protect like
var unprotect = MachineKey.Unprotect(Encoding.UTF8.GetBytes(myOldEncryptedStuff), "");
and if you in turn have some other code there like "User 12345" to help protect that data - this is called the purpose string and helps keep that string encrypted in a more unique way tied to that user.
var unprotect = MachineKey.Unprotect(Encoding.UTF8.GetBytes(myOldEncryptedStuff), "User 12345")
If the purpose strings don't match you'll just get a generic exception here like:
System.Security.Cryptography.CryptographicException: Error occurred
during a cryptographic operation.
So it won't work for you - the two methods operate very differently. You'll need to figure out when to use one vs the other. You could always catch the exception and then try to fallback to the old tech - but test that out :)

Objects stored by riak-java-client end up as raw json when read by riak-python-client?

I might be confused about something, but when I store a custom object from the Java Riak client and then try to read that object using the Python Riak client, I end up with a raw json string instead of a dict.
However, if I store a the object in python, I am able to output a python dictionary when fetching that object.
I could simply use a json library on the python side to resolve this, but the very fact that I am experiencing this discrepancy makes me think that I am doing something wrong.
On the Java side, this is my object:
class DocObject
{
public String status; // FEEDING | PERSISTED | FAILED | DELETING
public List<String> messages = new ArrayList<String>();
}
class PdfObject extends DocObject
{
public String url;
public String base_url;
}
This is how I am storing that object in Riak:
public void feeding(IDocument doc) throws RiakRetryFailedException {
PdfObject pdfObject = new PdfObject();
pdfObject.url = doc.getElement("url").getValue().toString();
pdfObject.base_url = doc.getElement("base_url").getValue().toString();
pdfObject.status = "FEEDING";
String key = hash(pdfObject.url);
pdfBucket.store(key, pdfObject).execute();
}
And this is what I am doing in Python to fetch the data:
# Connect to Riak.
client = riak.RiakClient()
# Choose the bucket to store data in.
bucket = client.bucket('pdfBucket')
doc = bucket.get('7909aa2f84c9e0fded7d1c7bb2526f54')
doc_data = doc.get_data()
print type(doc_data)
The result of the above python is:
<type 'str'>
I am expecting that to be <type 'dict'>, just like how the example here works:
http://basho.github.com/riak-python-client/tutorial.html#getting-single-values-out
I am perplexed as to why when the object is stored from Java it is stored as a JSON string and not as an object.
I would appreciate if anybody could point out an issue with my approach that might be causing this discrepancy.
Thanks!
It would appear you've found a bug in our Python client with the HTTP protocol/transport.
Both the version you're using and the current one in master are not decoding JSON properly. Myself and another dev looked into this this morning and it appears to stem from an issue with charset parameter being returned from Riak with the content-type as Christian noted in his comment ("application/json; charset=UTF-8")
We've opened an issue on github (https://github.com/basho/riak-python-client/issues/227) and will get this corrected.
In the mean time the only suggestion I have is to decode the returned JSON string yourself, or using the 1.5.2 client (latest stable from pypy) and the Protocol Buffers transport:
client = riak.RiakClient(port=8087, transport_class=riak.RiakPbcTransport)
it will return the decoded JSON as a dict as you're expecting.

How to pass a NULL value to a WCF Data Services' service operation?

I have a WCF data services' service operation such as
[WebGet(UriTemplate = "GetData")]
public IQueryable<string> GetData(int code, int deviceid, int groupId, DateTime dateTimeFrom, DateTime dateTimeTo)
{ ...
}
I am calling this service operation by sending a HTTP request to the server in this format:
http://localhost:6000/GetData?code=0&deviceId=1&groupId=0L&dateTimeFrom=datetime'2013-01-31T15:36:50.904'&dateTimeTo=datetime'2012-02-01T15:36:50.904'
and it is working like a charm.
Now I want to pass a NULL value as one of the parameters. How do I do that? Do I need to use nullable types such as "Int?" in the service operation declaration? How do I encode the NULL value in the URI?
Yes - you need to declare the parameter as nullable. Then you can simply omit the parameter (if it's nullable it will be treated as null then).

Why does Cache.Add return an object that represents the cached item?

From MSDN about the differences between Adding or Inserting an item the ASP.NET Cache:
Note: The Add and Insert methods have
the same signature, but there are
subtle differences between them.
First, calling the Add method returns an object that represents the
cached item, while calling Insert does
not. Second, their behavior is
different if you call these methods
and add an item to the Cache that is
already stored there. The Insert
method replaces the item, while the
Add method fails. [emphasis mine]
The second part is easy. No question about that.
But with the first part, why would it want to return an object that represents the cached item? If I'm trying to Add an item to the cache, I already have/know what that item is?
I don't get it. What is the reasoning behind this?
Calling Add() on a cache eventually calls an internal method with this signature:
internal abstract CacheEntry UpdateCache(CacheKey cacheKey,
CacheEntry newEntry, bool replace, CacheItemRemovedReason removedReason,
out object valueOld);
Notice the out object valueOld - this gets set to the object that is currently in the "cacheKey" location in the cache, and is returned as the result of Add(). The documentation is misleading, it's not actually the same object that is returned - it's whatever object was at that same key location.
This is easily verified with the following code:
String x = "lorem";
String y = "ipsum";
HttpContext.Current.Cache.Add("hi", x, null, DateTime.MaxValue,
Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
var z = HttpContext.Current.Cache.Add("hi", y, null, DateTime.MaxValue,
Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
//Result:
// z == "lorem"
To make this even clearer, here's a console app that demonstrates the exact behavior:
static void Main(string[] args)
{
string key = "key";
HttpRuntime.Cache.Add(key, "first", null/*no depends*/, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null/*no callback*/);
var addResult = HttpRuntime.Cache.Add(key, "second", null/*no depends*/, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null/*no callback*/);
Console.WriteLine("addResult = {0}", addResult);
Console.WriteLine("Cache[key] = {0}", HttpRuntime.Cache[key]);
}
And the console output:
addResult = first
Cache[key] = first
The "second" call to .Add returns what is currently in the Cache under our key and fails to update the entry!
If the Add method call succeeds in adding the item, it returns null.
If the key already exists in the cache, the method returns an object. However, the documentation doesn't say if it returns the object that you tried to put in the cache or the object already stored in the cache.
Logically it should return the object already in the cache, as that is the only information that is interresting. You already have a reference to the object that you try to put in the cache.
It only returns an object if the same object was already stored in the cache (under another key I guess under the same key). Otherwise it returns null. The documentation is misleading:
http://msdn.microsoft.com/en-us/library/system.web.caching.cache.add.aspx
Looking at it in Reflector, both methods seem to call the same internal method, with ADD returning the old object previously stored under the same key, and the INSERT method simply ignoring that value.

Resources