Sunday, 30 April 2017

Angular automatically unsubscribe from Observable

RxJs is amazing library but it come with the problem and problem is two types, Hot and Cold observable, from one your need to unsubscribe from other not.

Even people understand the difference sometimes they just simply forget to unsubscribe, and same happened in my project there were couple of bugs simply because developer forgot to unsubscribe.

One of the simplest solution is to hold subscription properties and on ngDestroy just simply call unsubscribe.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnDestroy, OnInit {
  private intervalSubscription: Subscription;
  ngOnInit(): void {
    this.intervalSubscription = Observable.interval(100)
      .subscribe((i) => console.log("Call without unsubscribe"))
  }

  ngOnDestroy(): void {
    this.intervalSubscription.unsubscribe();
  }

  title = 'app works!';
}

But first I need to remember about that, second I need to hold extra property which in many cases i just dont need.

So I came up with simple solution which works for me

First I've introduced base-component.ts with two methods one to add subscription and second will call unsubscribe on all items

import { Subscription } from 'rxjs/Subscription';
import { Observable } from 'rxjs/Observable';
import { OnDestroy } from '@angular/core';
import "./safe-subscribe"

export class BaseComponent implements OnDestroy {
    private _subscriptions: Subscription[] = [];
    public ngOnDestroy(): void {
        for (let sub of this._subscriptions) {
            sub.unsubscribe();
        }
    }

    public markForSafeDelete(sub: Subscription) {
        this._subscriptions.push(sub);
    }
}
Second I have extended observable and added new method safeSubscribe which is just a wrapper and require one more parameter of component instance to be base component

import { Observable } from "rxjs/Observable";
import { BaseComponent } from "app/base-component";
import { Subscription } from "rxjs/Subscription";

export function safeSubscribe(this: Observable, component: BaseComponent,
    next?: (value: T) => void, error?: (error: T) => void, complete?: () => void, ): Subscription {
    let sub = this.subscribe(next, error, complete);
    component.markForSafeDelete(sub);
    return sub;
}
Observable.prototype.safeSubscribe = safeSubscribe;

declare module 'rxjs/Observable' {
    interface Observable {
        safeSubscribe: typeof safeSubscribe;
    }
}

Now final solution will look like

export class AutoUnsubscribeComponent extends BaseComponent implements OnInit {
  ngOnInit(): void {
    Observable.interval(100)
      .safeSubscribe(this, (i) => console.log("Call without unsubscribe"))
  }
}

If component is in memory I can see console log is printing message if I remove component then nothing is added to console anymore

In addition safeSubscribe still returns Subscribtion so event if you need you can use it

The only problem now each developer should know what to call but i will think how to prevent using subscribe in my code using linting.

Source code can be found here

Sunday, 22 January 2017

Angular 2 - Manage application version

Problem

How to add build version to angular apps when building an app. Firstly I was looking how to solve this problem with angular-cli and did not found anything, then I found stackoverflow question and wrote small script which accept version from build. 

Solution

But after that I actually start thinking how to improve that solution and I finally come with a bit better solution. First of all i went of from angular and angular-cli to node. In node there is already done versioning.

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]


This is exatly what i was looking for since now my builds can call update patch version and i can use this version in prod versions of my builds.

Now to get it together

1. Install npm install replace-in-file --save-dev this plugin will help to replace version file.

2. Insert to environment.ts new property to hold version

environment.ts

export const environment = {
  production: false,
  version: 'DEV'
};


environment.prod.ts

export const environment = {
  production: false,
  version: '0.0.0'
};

3. Insert build script to your project

var replace = require('replace-in-file');
var package = require("./package.json");
var buildVersion = package.version;
const options = {
    files: 'src/environments/environment.prod.ts',
    replace: /version: '(.*)'/g,
    with: "version: '"+ buildVersion + "'",
    allowEmptyPaths: false,
};

try {
    let changedFiles = replace.sync(options);
    if (changedFiles == 0) {
        throw "Please make sure that file '" + options.files + "' has \"version: ''\"";
    }
    console.log('Build version set: ' + buildVersion);
}
catch (error) {
    console.error('Error occurred:', error);
    throw error
}

4. Update package.json and insert new script

"build-prod": "npm version patch && node ./replace.build.js && ng build --prod"

How it works

Now you can run from command line npm run build-prod it will update version in package.json, then read updated version from package.json and store it in environment.

What else

Now manipulating npm version you can define multiple your version for instance npm version minor will increase your minor and automatically reset patch version.

Friday, 20 January 2017

Debug Protractor typescript tests with VsCode

Problem

I've been looking around how to debug unittests written on typescript with protractor and I was not able to do it.
There was many tutorials how to debug with javascript but non about typescript.
After reading source code I have found that protractor is using ts-node  so i started googling how to run debug and found an issue that its not possible to debug. The main problem as I understood is that ts-node is keeping files in memory so VSCode cant access them.

Solution

The solution would be to compile, and then run protractor from compiled sources.

Go!

Update package.json and add new script


"e2e-compile": "tsc -p e2e"

Then in VSCode press Ctrl+Shift+P to create npm task. It will create file in .vscode/tasks.json


{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "npm",
    "isShellCommand": true,
    "showOutput": "always",
    "suppressTaskName": true,
    "tasks": [
        {
            "taskName": "e2e-compile",
            "isBuildCommand": true,
            "args": [
                "run",
                "e2e-compile"
            ]
        }
    ]
}

Create in root folder protractor.config.debug.js

var SpecReporter = require('jasmine-spec-reporter');

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './dist/out-tsc-e2e/**/*.e2e-spec.js'
  ],
  capabilities: {
    'browserName': 'chrome'
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },
  useAllAngular2AppRoots: true,
  beforeLaunch: function() {
   
  },
  onPrepare: function() {
    jasmine.getEnv().addReporter(new SpecReporter());
  }
};

Create debug config .vscode/launch.json


{

    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch e2e Tests",
            "type": "node",
            "request": "launch",
            "stopOnEntry": false,
            "program": "${workspaceRoot}/node_modules/protractor/bin/protractor",
            "args": [
                "${workspaceRoot}/protractor.conf.debug.js"
            ],
            "preLaunchTask": "e2e-compile",
            "cwd": "${workspaceRoot}",
            "sourceMaps": true,
            "outFiles": [
                "${workspaceRoot}/dist/out-tsc-e2e/*.js"
            ]
        }
    ]
}

Done!

We are almost done. 
NOTE! If you are running for first time then npm run e2e it will install and update webdriver.

Now we are done you can run debug, and see what is going in your unit tests, but remember that by default protractor come with jasmine and when you are debugging you are dealing with promises.


Source Code can be found here 

Tuesday, 13 December 2016

RxJS - Why its so amazing or how to write own operator

Introduction

When I started with observable I did not get why RxJs is so popular since I thought they are implementing observer pattern which was long time ago. Also I did not understand why people always call them stream or flow, so this is how my journey started with RxJs.
It’s a huge topic about what is included and how it works.  I will generally concentrate on operators this time since this on of features makes RxJs so amazing. http://reactivex.io/documentation/observable.html

Other interesting topic for me is Subjects http://xgrommx.github.io/rx-book/content/subjects/index.html,

1. private _eventFlowStopper = new BehaviorSubject<boolean>(false);
2. private _eventsObservable: Subject<EventFlow> = new Subject<EventFlow>();

BehaviorSubject always require initial value and could be used for cases such as settings, when application on initialization gets some default value. In addition difference is that when we subscribe to Subject, subscribe event will be emited only if there is something new broadcasted after subscription, meanwhile BehaviorSubject will send data immediately after subscription. So as soon as any part of app will subscribe to eventFlowStopper  it means that it will get latest value in this case it will be false since noting was send to eventFlowStopper

Operators  

It does not make sense to copy/paste info to here from official doc http://reactivex.io/documentation/operators.html  so read it :)
But I would like to mentioned why this  part is worse to study in RxJs
- Chaining - you can chain observable which gives you different way to make your own flow
- Many built in operators - If you want to delay event, debounce, remap its already there you can use it straight away
- You can write your own - Yes if you have special case you can write your own operator

How it works

Observable object have method lift (https://github.com/ReactiveX/rxjs/blob/master/src/Observable.ts#L67) which create new observable so it means that if we apply filter (http://xgrommx.github.io/rx-book/content/observable/observable_instance_methods/filter.html) then we will end up with two Observable streams.

Let's play: Requirements

Reading is good but practice is always much better actually when I wrote this simple app I discovered lots of small details :)
So let's assume we have Application where event flow throw channel
- If event of type "First" is send it means that channel should be paused for some time
- If event of type "Second" is send it means that from now and till this event is disabled, only type Second is allowed and type First goes to buffer;
This pretty simple what I am doing, in my app I have observable which is receiving events from SignalR. And that operator will APPLY logic to stream such as delay or allow specific type.

Operator

Full source code for operator you can see at (https://github.com/vovikdrg/rxjs_operators/blob/master/src/app/event.flow.operator.ts).
Since I have done my functionality I will go reverse way as I did while implementing.
I like the possibility to extend of course I am lazy and I expect framework to have all I need but if in some cases it is not implemented I don’t want to look for other lib I want to extend what I am using.

Firstly lets create method definition who will create new observable with EventFlowOperator.

export function controlledEventFlow(this: Observable<EventFlow>, stopNotifier: Observable<boolean>, allowTypeOnly: Observable<string>): Observable<EventFlow> {
    return this.lift(new EventFlowOperator(stopNotifier, allowTypeOnly));
}
- this: Observable<EventFlow> - this will limit usage to observable of type Event flow
- stopNotifier: Observable<boolean> - this will notify subscriber that no events are allowed to send
- allowTypeOnly: Observable<string> - notify subscriber that from now only this type is allowed to send



Now to allow typescript to compile we need to extend observable

declare module 'rxjs/Observable' {
    interface Observable<T> {
        controlledEventFlow: typeof controlledEventFlow;
    }
}

And prototype created function

Observable.prototype.controlledEventFlow = controlledEventFlow;

Then lets create our operator

class EventFlowOperator implements Operator<EventFlow, EventFlow> {
    constructor(private stopNotifier: Observable<boolean>, private allowTypeOnly: Observable<string>) {
    }

    call(subscriber: Subscriber<EventFlow>, source: any): any {
        return source._subscribe(new EventFlowSubscriber(subscriber, this.stopNotifier, this.allowTypeOnly));
    }
}

NOTE: call method will be called so many times as we subscribe to this observable it means that EventFlowSubscriber will be created for each subscription.

EventFlowSubscriber
- Constructor - here we subscribe to notifier members to be able to lock and set filters
○ Both notifers have debounce operator to make sure that only latest is delivered.
- _next - overriding base method to push data to buffer and call method to send data
- deliverNext - this method will send data to subscribers

Components

Components are responsible to handle specific event type and pause or enable filtering of specific types.
When I started my app I have used setTimeout for delay but later I have discovered that observable actually has TimerObservable.create which allows to create timeouts and intervals.

 this._timer = TimerObservable.create(2000);
this._eventService
      .events
      .filter(e => e.type == 'First')
      .subscribe(e => {
        console.log(e);
        this.events.push(e);
        this._eventService.eventFlowStopper.next(true);
        var subscription = this._timer.subscribe((n) => {
          subscription.unsubscribe();
          this._eventService.eventFlowStopper.next(false);
        })
      });

 TimerObservable is cold observable which means that nothing is broadcasted until it gets subscriber.

Event Service 

Case


  private _eventsObservable: Observable<EventFlow>

  constructor() {
    this._eventsObservable = this.PushEvents
      .controlledEventFlow(this._eventFlowStopper, this._allowType);  
  }

Startup

When app is runned two components are subscribed to eventsObservable via public get events(): Observable<EventFlow> and as I mentioned before two EventFlowSubscriber will be created because of   return source._subscribe(new EventFlowSubscriber(subscriber, this.stopNotifier, this.allowTypeOnly));
Events
PushEvents.next(new EventFlow("First", new Date()));
PushEvents.next(new EventFlow("First", new Date()));
PushEvents.next(new EventFlow("Second", new Date()));

Flow

1. EventFlowSubscriber._next pushed event to buffer and called deliverNext
2. EventFlowSubscriber.deliverNext will deliver event to DisplayFirstTypeComponent because all if statements are false.
3. After DisplayFirstTypeComponent received data it sends eventFlowStopper.next(true); this means that now value is true
4. And here is trick since we have 2 subscribers then EventFlowSubscriber._next is called for DisplaySecondTypeComponent and now this.flowStopper is true and it means that event is not delivered to component + state of both buffers is different in first subscriber is now -1 item and second will stay the same.
5. After 2 seconds DisplayFirstTypeComponent will emit false to stopNotifier and First subscriber will deliver next message to First component components, which will switch back stopNotifier to true, but here is one more important thing is that Second subscriber will receive stopNotifier as true and then immediately  false. Look at time 54.450.

Solution

Well here is pretty easy solution in the service I can create one more observable where we will put data from controlledEventFlow subscription.
Change code in service to

  private _eventFlowStopper = new BehaviorSubject<boolean>(false);
  private _allowType = new BehaviorSubject<string>("");
  private _eventsObservable: Subject<EventFlow> = new Subject<EventFlow>();

  constructor() {
    this.PushEvents
      .controlledEventFlow(this._eventFlowStopper, this._allowType)  
      .subscribe(ev=> this._eventsObservable.next(ev) );
  }

And now I get behaviour I need


Source code

Saturday, 21 May 2016

Hight traffic usage on Azure Web App + Sql Server on VM

Preavious post was about trafic, and this one is not an exception. When i log in to azure portal into billing i was a bit surprices to see
Well for somebody it could be ok but for my project where i have around 3000-4000 people everyday it is too much.

The first thing I've done was writing to support, but they just confirmed that everything is right and i am actively using all what i am billed. 

By coincidence at the same time i started playing with Azure sql and it was extremaly slow, some queries were running almost twice time more than in my current setup, at that point I debug queries and was a bit of surprise how much data i am transfering from database to webapp, since in many queries i am using entityframework Include (I will start optimizin that and will write one more blog post about that) and it means it try to get everything in one request but using joins.

After that i understood that actually issue is with traffic between database and webapp, so i went to azure and start reading again about gateway and i found that all traffic which is going throw gateway is paid.  

Solution

I should never ever use gateway to connect to any server inside of azure. Gateway should be used ONLY when database machine is out of azure network.
Open end point in Azure Database VM


Connection String to Sql Server on Azure VM should look like 
"Server=mydbserver.cloudapp.net,57500;Integrated Security=false;User ID=<login_name>;Password=<your_password>"
If you have same problem please vote for suggestion it would help to understand which service is using.

Result




Lesson learned

Gateway is evil. Entityframework is evil. Each time I think Microsoft is doing something wrong it means that i fucked up somewhere :)
And last thing: Cloud are powerful, but mistakes could cost you alot.

Wednesday, 20 April 2016

Save traffic for your website and improve loading speed, Azure CDN, Asp.Net MVC

Last month I started monitoring how much my website cost to host on Azure, and I was surprised that I am paying around 25USD for traffic which I should not generate. Firstly I did not understand what is going on and what is generating so much traffic, since before I was using VPS and i did not pay for that so I started investigation

Chrome

I am using chrome by default so it was easy to get what is going on (Pressing F12->Network).
So each visit to my site generates only on one script 534Kb + 18.6 and its only on javascript but i have css, images so on.

Use cache

First step to improve that was enabling cache in web.config
<staticContent>
      <clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="90.00:00:00" />
</staticContent>

Now if we compare network in chrome its possible to see that script is loading from cache


CDN

To speed up even more loading of static files I created new CDN on Azure. And cool thing about it that it actually require zero configuration. After CDN its pretty easy to configure it, usig existing web app.

How CDN works

It will check in browser cache if file exists, if not it will check if file is in CDN cache and if not it will load from WebApp. (This solution its not right, since better would be if I have deployment tasks which will deploy binary to webapp, and static file to CDN, but this private project and I dont have much time to do everything right :( ) 


Monday, 14 December 2015

Elmah filter by exception type

In Elmah there two ways to filter exception

  1. by code
  2. by config
In this post i will just show how to filter exception using config file this is pretty simple 


  <elmah>
    <errorFilter>
      <test>
        <or>
          <equal binding="HttpStatusCode" value="404" type="Int32" />
          <is-type binding="BaseException" type="Namespace.BaseException, AssembyName" />
        </or>
      </test>
    </errorFilter>
  </elmah>

So current config will ignore all 404 and exception who inherited from BaseException.  But note that important thing is that assembly name is specified or elmah will try to search in Elmah assembly which will cause an error