Monday, January 16, 2017

Angular Factory for $resource and dynamic header content

I created a Factory recipe for my $resource instance.

There are multiple ways to create it. I used this approach.

  angular.
    module('myModule').
    factory('myService', ['$resource', '$localStorage',
      function($resource, $localStorage) {
        var url = 'xxx';
        return $resource(url + '/my-resource/:id', { id: '@id'}, {
          query: {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
              'X-Auth-Token': $localStorage.token
            },
            isArray: true
          },
 ...
]);
It was working fine till I notice this issue.

If I logout and login as different user the old token was being used!!!

This is because the Service and Factory instances are Singleton. On logout we clear data and not the object of the app in the browser. The first value of $localStorage.token is used to create the instance and that does not get updated even when the value $localStorage.token changes.

One approach to fix this would be create 
  angular.
    module('myModule').
    factory('myService', ['$resource', '$localStorage',
      function($resource, $localStorage) {
        var url = 'xxx';
return { GetInstance: GetInstance };
function GetInstance(token) {
        return $resource(url + '/my-resource/:id', { id: '@id'}, {
          query: {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
              'X-Auth-Token': token
            },
            isArray: true
          },
}
 ...
]);

In the controller  myService.GetInstance( $localStorage.token).query()

This is more work.

The better approach would be to get the 'X-Auth' dynamically. This can be achieved by using a function instead of value.

angular.
    module('myModule').
    factory('myService', ['$resource', '$localStorage',
      function($resource, $localStorage) {
        var url = 'xxx';
function GetToken() {
 return $localStorage.token;
}
        return $resource(url + '/my-resource/:id', { id: '@id'}, {
          query: {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
              'X-Auth-Token': GetToken
            },
            isArray: true
          },
 ...
]);

Thursday, December 22, 2016

Sublime copying all text that match a pattern

I had a text file containing numbers in between text that I wanted to copy, move to a new file and format them.

Since the numbers were of of fixed length and at the same index I could have copied them using vertical select. The vertical select is tricky if the file is big and it wouldn't help if the pattern to looks for is different and can occur anywhere in the text.

I knew the first way was to write a regular expression for the pattern that I was looking for. I could highlight all the matches with my pattern. But now how do I copy it?

https://forum.sublimetext.com/t/copy-matching-lines/5877/2

I couldn't beleive it could be as simple as clicking Find All. The Find All gives a cursor to all the match with text selected. Amazing!!!

So Ctrl+c will copy all of them. Bravo!

I put the data on another file where I have to format them. This was easy. I used replace and group capture.

Find :      (455\d\d\d\d\d\d)
Replace : ($1),

The above will put all the matches within ( ... ),

Again I would have used Find All and used the cursor to modify all the words and put the brackets around them.

Thanks to sublime!!

Wednesday, December 21, 2016

Creating a dynamic table out of list of numbers to join


I had a list of ids and I wanted to check which rows are not present in the DB.

We can use 'in (1, 2, 3)' and that would say which ones are in, and 'not in' would return rows outside the ids I had.

So I wanted to make a table out of the ids and use left or right join.

I could not find any simple way of doing this and then the approach mentioned here http://stackoverflow.com/questions/8002178/how-to-select-ids-in-an-array-of-ids

select * from (
select TO_NUMBER(xt.column_value) id1 from
xmltable(
'123456,
123457,
123458,
123459') xt) a
left join my_table mt on mt.id = a.id1
where mt.id is null

Indeed I had 1000 of Ids in my list and not the above 4 :)

I choose left join as my_table had thousands of rows.

I really appreciate effort of anyone to answer on SO.

Tuesday, December 20, 2016

Query join with View - Oracle Performance

I had a slow running query that joined on two views, A and B. I had this wrong understanding that the query is slow as it prepares the whole view and then runs the query on the view. This was totally incorrect.

Consider view in a join as a sub-query. The optimizer would try to minimize the cost.In my case the join with view A performed better than the join with view B. Both had approximately same amount of data.

I went through the following articleshttps://blogs.oracle.com/optimizer/entry/optimizer_transformations_view_merging_part_1https://blogs.oracle.com/optimizer/entry/optimizer_transformations_view_merging_part_2https://blogs.oracle.com/optimizer/entry/basics_of_join_predicate_pushdown_in_oracle
And the explain plan proved it all.The join with view A was merged as index joins in the query with base table. The reason being view A had none of this (was a simple select with inner join)
  • UNION ALL/UNION view
  • Outer-joined view
  • Anti-joined view
  • Semi-joined view
  • DISTINCT view
  • GROUP-BY view

While View B had many outer joins and an outer join with another view, C. The outer joins on tables were moved to View pushed predicate.


The optimizer does a view merge for a view with outer join when it is possible to do so.

The join on view C was expensive as it was a HASH join.

Thursday, August 18, 2016

Avro - schema change compatibility

I was under the impression that I can add an optional field to Avro schema and consumers with old schema would still be able to read the message whether or not the newly added optional filed is set or not in the record.

So I added an optional field to an Avro schema, generated an Avro from it and I was able to read it from consumers using the old and new schema (this might not work if the schema changes are not at the end).

But this is not how it should work as the Avro schema is not forward compatible. And that is what happened and one of the consumers started to fail.

So I was surprised why my code was working and the other code (using older schema) was throwing errors when reading the avro created out of new schema. This is where it was failing


    BinaryDecoder binaryDecoder = DecoderFactory.get().binaryDecoder(is, null);
    while (!binaryDecoder.isEnd()) {
      DatumReader<MyClass> datumReader = new SpecificDatumReader< MyClass >(MyClass.class);
      datumReader.read(null, binaryDecoder); // failure here
    }

The difference was, I didn't had the while loop in my code, assuming the input stream represented a single record, while the other consumer was handling a batch of requests.

So the above code would read part of the avro byte array as per the old schema in the first iteration and the remaining bytes for the new field (even though it is not set) in the second iteration. Since the left bytes was not a complete record it was reporting errors.

Tuesday, March 29, 2016

Map.get - KeyNotFound error

It is interesting how different languages approach towards a given problem.

Let's have a look at how different languages react while trying to read a key from dictionary

Java

map.get('key_that_does_not_exist')

=> null

Ruby

map['key_that_does_not_exist']

=> nil 

Python

>> x['key_that_does_not_exist']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'key_that_does_not_exist'

>> x.get('key_that_does_not_exist)
=> None

Scala

val x = Map("a" -> "1”)
x("key_that_does_not_exist”) // Throws exception
x.get("key_that_does_not_exist”) // None

Sunday, February 22, 2015

JDK in OSX

I wanted to figure out the Java installation on OSX so that I can easily switch between JDK 6,7 and 8.

I got my answer from this post http://stackoverflow.com/questions/15120745/need-help-understanding-oracles-java-on-mac

In summary

When we install Java using a dmg it goes here /Library/Java/JavaVirtualMachines/

This command is handy to figure this out

$ /usr/libexec/java_home 

/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home

java_home man
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/java_home.1.html

Let's see how this gets connected with java command.

$ java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

$ which java
/usr/bin/java

$ ls -al /usr/bin/java
lrwxr-xr-x  1 root  wheel  74 Apr  2  2014 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
</pre >

/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java is actually a proxy to actual installation of java!

Let's see where does this proxy end up

$ sudo dtrace -n 'syscall::posix_spawn:entry { trace(copyinstr(arg1)); }' -c "java -version"
dtrace: description 'syscall::posix_spawn:entry ' matched 1 probe
dtrace: pid 19903 has exited
CPU     ID                    FUNCTION:NAME
  0    638                posix_spawn:entry   /Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/bin/java

from the post
A combination of factors are considered. JAVA_HOME is used if set (try JAVA_HOME=/tmp java). If JAVA_HOME is not set then the list of all virtual machines on the system is discovered. The JAVA_VERSION and JAVA_ARCH environment variables are used, if set, to filter the list of virtual machines to a particular version and supported architecture. The resulting list is then sorted by architecture (preferring 64-bit over 32-bit) and version (newer is better), and the best match is returned.
The proxy is intelligent enough to find the Java installation and java will work for you. But what if you want to switch between multiple JDKs. Simple, pass the instruction through JAVA_HOME. export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home

No need to add to the PATH :) 

I love this proxy concept. An Apple A Day, Keeps lot of worries Away