Ehcache: storing null to indicate missing value vs. "not cached yet"? - ehcache

I would like to use Ehcache in the "cache-as-sor" configuration (read-through + write-through), so it would hide database interaction from the parent process.
In my case, it can happen that for a requested key, the corresponding value does not exist at all in the underlying database. So, in order to avoid querying database every time get(key) is called for a non-existent value, I would like to store in the cache the fact that the value is missing. The first thing that comes to my mind is to store null values for that; so, if ehcache.containsKey(key) returns false, I need to consult the database and update the cache; but if ehcache.containsKey(key) returns true but ehcache.get(key) returns null, it means the value will never be there and I don't have to query the DB.
However, the Ehcache documentation states that put(key, null) is not allowed.
How to handle such scenario then?

Use a NullObject. So instead of storing null, you store some object that you know represents null.

Related

Redis : Get all keys by providing one of the value in the values list

In redis I'm planning to store key as a unique string and value will be a list.
I have a use case where I need to do 2 things.
First, I need to get all the values associated with a key by providing the key as input.
Second, I want to get all the keys associated with a value by providing one of the value in the values list.
Second part is where I need the advice, how we can achive this ?
I cannot get all the keys or key value pair and loop through because I will have millions of entries in Redis.
As mentioned in the comment above the retrieving of all keys with associated value at will probably sometimes create a performance issue as this will be a run through large entries.As also suggested in the official documentation about retrieving data from the memory caches you can try and use the following Redis command to get the value and see if that is what can solve your purpose.
GET
MGET

PreparedStatement - set param to DEFAULT (keyword)

Although this question seems to be close to this one, it is actually different.
Question
Is there any way to specify DEFAULT value as a parameter in JDBC's PreparedStatement?
Use-case
I'd like to have a single statement used for several inserts (or batch) into the table having some column defined as, say:
updated TIMESTAMP NOT NULL DEFAULT TIMESTAMP.
Now, assume that I got a non-uniform set of entries to insert, some of them DO have a value for that column while others DOESN'T (effectively relying on the DB to generate it).
Instead of 'divide and conquer' pattern (which obviously may become exponentially complex if there are more columns like this), I'm looking to run the same PreparedStatement in the single batch, while specifying DEFAULT value for all those entries that DOESN'T have the required values.
Well, seems that a statement of the #a_horse_with_no_name is straight forwardly to the point.
Gone over the PreparedStatement Java 9 docs again and found no hints to anything even close to this.
I'm missing a functionality to set parameters to a DB functions/keywords like DEFAULT, CURRENT_TIMESTAMP etc, but that's the state of PreparedStatement as of now.

How to update distributed cache under high traffic and multiple applications?

I have N services that use M redis as the remote distributed cache. Suppose now multiple services want to retrieve the same key, and the following pseudo codes are how the work is done:
redisClient = getRedisClientByConsistentHash(key)
value = redisClient.get(key)
if value not exist
value = getValueFromSomewhereElse(key) // line4
redisClient set key value ex 1 nx // line5
return value
So the problem is:
In "line4", if 2 applications retrieve different values, one is newer and the other is old(should be deprecated), it's possible that the call to store the old value will happen before the call to store the new value, thus the new value won't be stored in redis. If we introduce some distributed lock mechanism, the problem still remains.
If the Key Storage internally makes use of timestamp of key in a way such that if KeyA is required to be updated from ValueA to ValueB then this updation is possible only if ValueB is inserted at a time which is greater than last updated timestamp of KeyA. Then its guaranteed that only new values will be inserted in a particular Key Storage. OldValues cannot overwrite NewValues (Timestamp Based Protocol). (Don't know whether redis follows Timestamp Based Protocol).
Both of your 2 applications (say, A, B) tried to fetch key from their respective primary redisClient and did not find the key and hence they went to fetch the key from SomewhereElse and found the key, but A has old and B has new. In such case there are few questions:
1. What if A's or B's primary `redisClient` itself gave you a value which is old?
2. How you come to know the value which is fetched is old or new?
Solutions:
1. Use a value which has majority (i.e the value received from atleast [ceil(M+1)/2] redisClients). Ofcourse this involves querying atleast [ceil(M+1)/2] rediClients which seems expensive. (Paxos Theorem)
2. Depending upon application logic, most of the time you don't require latest values. That is, if the application requirement is to just check the presence of a value then it does not matter whether the value is old or new.

How to get value from a specific row and column in MS ACCESS database?

First, I don't have unique value to directly point out a value I want to retrieve, so there for, I cannot use the WHERE Statement. The reason for that, because I have a database where I constantly updated or deleted, so if I use WHERE statement I have to edit the code again.
Then do apply a unique value - add a field of data type AutoNumber or you will never get out of this mess.

ServiceNow Encoded Query validation

I intend to let users specify encoded query in ServiceNow SOAP requests.
The problem is that if user specifies invalid query string (e.g. "?##" or "sometext"), ServiceNow do not return any exception, but every row or no rows at all.
Is there a way to check validity of encoded query via webservice?
Fandic,
If you know ahead of time which table the SOAP query will be running against (or can get that information from the user when they submit the query) you can set up your own web service exclusively for checking the validity of a query string.
GlideRecord has the "addedEncodedQuery" method for putting in encoded queries, and it has a getEncodedQuery for turning the current query into an encoded string. If you instantiate a GlideRecord object, and pass it an invalid query string like this:
var myGR = new GlideRecord('incident');
myGr.addEncodedQuery('invalid_field_foo=BAR');
You can then call getEncodedQuery out to see if it is valid:
var actual_query = myGR.getEncodedQuery(); //sys_idNotValidnull
You shouldn't do simple comparison between the input and the output, as the API doesn't guarantee that a valid query will be returned as the exact same string as entered. It's better to simply validate that the actual_query does not equal 'sys_idNotValidnull'.
I always recommend enabling the system property 'glide.invalid_query.returns_no_rows' to avoid this effect. The property does just what it says. I never understood why you'd ever want to return all rows for an invalid query. I've seen a number of cases where developers had a query defect and never knew it since rows were coming back.
You can use the below code so that query will return the result only when it correct.
gs.getSession().setStrictQuery(boolean);
This overrides the value of system property :
glide.invalid_query.returns_no_rows
Reference : https://docs.servicenow.com/bundle/istanbul-platform-administration/page/administer/reference-pages/reference/r_AvailableSystemProperties.html
Check the property value glide.invalid_query.returns_no_rows. If it's true, the invalid query returns no rows. If false (or not available) it is ignored.
This can be overridden with gs.getSession().setStrictQuery(boolean); on a script-by-script basis.

Resources