Wednesday, 21 August 2024

Hosting a .NET Core 3.1 App in an IIS Virtual Directory

Virtual Directories are useful if you wish to host multiple sites on different sub paths. Like localhost/client1website or localhost/client2website.

I was getting 500 error when trying to host a .NET 3.1 application on IIS.


Suggestions were

1) app pool - yep I had checked and checked again, it was defitely set to "No Managed Code"

2) Check the IIS Logs - see below - calling Get to [virtualdirectory1]/[virtualdirectory2] on port 80 gets me a 500

3) Check the permissions. IIS_IUSRS has read and execute permissions

4) Check that the web.config has what it should have and nothing else. - yup checked that

5) Check the application logs - Attribute 'ProcessPath' is required

At this point getting closer with the app log message. Was there something up with how I installed dotnet? Am I missing a path variable?

I found someone saying that you should really have dotnet SDK as well as the hosting package so I installed the SDK. Nope

I set the dotnet path variable to "C:\Program Files\dotnet\dotnet.exe", Nope

Then I googled ".net core 3.1 process path error".

You get a lot, but third one on Stack Overflow -- 

'Make sure you right click on your Virtual Directory and select "Convert to app".' 

I really dislike IIS more than usual today :). But hey, I made it!

Attributions

Load configuration attribute QA on Stack Overflow

Thursday, 16 December 2021

React Router and NodeJS


Hosting your React app is usually as simple as copying over the files to a "public" or "static" directory.
 
You could simply paste the files onto an IIS or Apache Server and this article could still help you if you are using sub directories. However, I have written this to tackle the situation where a pre-existing web application will host, in this scenario the host application is written in NodeJS. 

Generally, all you need to worry about is serving the "index.html" file that comes in the production build bundle at the right time, something like: 
router.get('/myroute'async (req, res) => {
return res.sendFile(path.join(__dirname + '/public/client/index.html'));
}

// later on make the public directory accessible
app.use('/public'express.static(__dirname + '/public'));

However, in this case I want to use React Router to navigate to sub pages. e.g. myroute/ home, myroute/user etc...

The way to do it is to use a wildcard off of your main route so that your React app will load on every child route of "myroute":
// this is required to support any client side routing written in react.
router.get('/myroute/*', (reqres=> { 
    res.sendFile(path.join(__dirname + '/public/client/index.html'));
});
On the React application side the "basename" property of the Router wrapper component (in React Router 5+) needs to be set. In my case I set "base" when in production mode to "/myroute". This will mean React router will look for "/myroute/new" to render the Start component rather than just "/new".
const base = process.env.NODE_ENV === "production" ? "/myroute" : "/";

<Router basename={base}>
   <Switch>
     <Route exact path='/new'>
       <Start />
     </Route>
   </Switch>
</Router>
It is also worth mentioning that it is considered best practice to add a href meta tag to you index.html page.

References
react-router | https://reactrouter.com/web
medium | https://dev-listener.medium.com/react-routes-nodejs-routes-2875f148065b

Friday, 9 October 2020

Generating a Schema for GraphQL

When writing the schema that you just defined elsewhere gets a little old....

I have been working on a graphql instance where the main data source is, currently at least, a mongo database. As you may have seen in my last blog post about defining graphql schema's, I was able to include a more useful set of scalar types to make my graph API easier to consume.

I did this using the merge tools in the graphql-tools library. Well, I found another use for those tools in my next TypeScript/Mongo/GraphQL adventure!

First of all I should point out that the process for using graphql-compose-mongoose is well documented in the readme of the library. To summarise, once a mongoose model has been defined it is necessary to define a detailed schema definition and resolvers for graphql. The schema definition and associated resolvers for graphql are a lot of work to write and maintain manually. Here is where this library steps in and helps you generate the types, input types, enumerations and resolvers. It really is quite the life-saver!

I was curious however, as to whether I could include it on top of the schema that I had already defined (see previous blog post). After googling around for a way to merge schemas I found out that it was available from the graphql-tools library that I was already using. So I was able to really easily.

import gqlTools from 'graphql-tools';
import gqlCompose from 'graphql-compose';
import monCompose from 'graphql-compose-mongoose';
const competitionTC = monCompose.composeMongoose(customModel, {});

gqlCompose.schemaComposer.Query.addFields({
	competitions: competitionTC.mongooseResolvers.findMany(),
}); const graphqlSchemaFromMongoose = gqlCompose.schemaComposer.buildSchema(); const existingSchema = gqlTools.makeExecutableSchema({ alreadyExistingTypeDefs, alreadyExistingResolvers, }); const allSchemas = gqlTools.mergeSchemas({ schemas: [ existingSchema, graphqlSchemaFromMongoose ] });

This code works beautifully, although it almost feels like it shouldn't. There is a lot going on and I found myself wondering whether it was all necessary. 

In the graphql UI the competitionTC now has a much more complete filter than the one I had before and skip, limit and sort also work great.


But, the code is messy 😉. Do I really need those extra scalar types?

Something went wrong  Error: Unknown type "Date".

OK then, turns out this is the best solution for now! It produces really complete GraphQL queries and mutations with very little effort.

Resources and references:

The ultimate guide to schema stitching in GraphQL

graphql-compose-mongoose

Tuesday, 29 September 2020

Defining a GraphQL Schema in TypeScript

Basic Example

In the documentation you will see something like this:

  import graphQL from 'graphql';
  
  // Construct a schema using GraphQL schema language
  export default graphQL.buildSchema(`
    type Customer {
      dob: String
    }
  `);
This is great for getting familiar with graphQL initially but what happens when I want to use a type that is not native? For instance, graphQL, out of the box, has only 4 "scalar types" - String, Int, Float and Boolean. 

So what if I want to deal with a date from my data source? Well there are a few things to know: regardless of the storage format graphQL will change it to a "Long Seconds" number (actually the number of millisecond's elapsed since 01-01-1970). Sure you can plug that into new Date on the frontend, but it is a potentially unnecessary cost for the browser in terms of performance and would mean that we must rely on the consuming developer to remember to tidy up our dates.

Diving in further

Such a limited number of Scalar types in graphQL does seem to invite extension and so we have "graphql-scalars". It does exactly what we want:
{
    "name": "Lewis Kinsella",
    "dob": "1994-09-02"
}

However, further inspection of the docs plus also the common use case test in the code base shows that this library works differently. Instead of using buildSchema we have "makeExecutableSchema" with some typeDefs and resolvers.

import gqlTools from 'graphql-tools';

const schema = gqlTools.makeExecutableSchema({
	typeDefs,
	resolvers,
});

So how do I change my existing work to fit with this?

Let's start at the end...

app.use('/graphql', graphqlHTTP({
	schema
});

It looks like resolvers are no longer added as the "root value" argument in the graphqlHTTP object.

Instead we are adding the schema object only. How do we make that?

const schema = gqlTools.makeExecutableSchema({
	typeDefs,
	resolvers,
});

The typeDefs here is mostly what we had before except now we need to merge in our extra scalar functionality.

a) resolvers are merged with the scalar tool resolvers.

const resolvers = gqlTools.mergeResolvers([root, scalarResolvers.resolvers]);
and
b) 
const typeDefs = merge.mergeTypeDefs([customTypeDefs, ...scalarTypeDefs.typeDefs]);

Where customTypeDefs is what we had at the beginning, no need to change it, except to add some extra scalar types!

 import graphQL from 'graphql';
  
  // Construct a schema using GraphQL schema language
  export default graphQL.buildSchema(`
    type Customer {
      dob: Date
    }
  `);
Happy graphQL-ing in TypeScript with Scalar types!

Wednesday, 9 September 2020

Azure Functions with TypeScript

Things to know about using TypeScript with Azure functions:

  1. Make sure that you have node installed using the latest LTS version (Long Term Support). If you need the latest version for other projects try using nvm-windows to manage multiple versions of Node. Install the latest version of nvm using the zip file in assets of the latest release. nvm list and then nvm use. Also nvm install v 64/32bit is pretty nifty.
  2. To run Azure functions manually (particularly useful for timers etc.. anything that is not an Http Trigger). http://localhost:<port>/admin/functions/<FunctionName>. Also for CRON timings see this cheatsheet.
  3. Azure Functions in TypeScript still use CommonJS modules, so while you can use imports and exports in your code the transpiled JS will be using Node style modules. Bear this in mind if you are expecting to be able to use any of your own libraries that compile to anything other than CommonJS. Check your TSConfig.
So is TypeScript support any good? So far it seems good, the only problems are with my own libraries. I have also noticed that you cannot use fat-arrows for Azure Index functions (for those not so familiar - the entry point called by Azure infrastructure).

Friday, 22 May 2020

Jest-diff Issue after upgrading react-scripts


A project I have been working on recently based on CRA (create-react-app) for TypeScript needed a large jump upgrade (3.1.1 to 3.4.0). Finally after working through a lot of other well documented problems I hit this one:

'=' expected. TS1005

The error occuring in the file jest-diff line 1:
import type { DiffOptions } from './types'

This was strange to me because I had not changed anything related to jest or my testing setup. 

Luckily I was able to find this github issue: https://github.com/facebook/jest/issues/9703

The user paulconlin got it spot on- I upgraded to TypeScript 3.8.3 and was able to compile again.

Tuesday, 20 August 2019

Excel files with .NET Core

I found myself needing to quickly manipulate some data in an excel sheet.

I had no access to the full blown Visual Studio, no problems I thought, let's see what VSCode, the command line and .NetCore 2 can do.

New project: no problem
Snideness aside it really is easy - just think of a project folder name...

  • dotnet new console 
  • dotnet restore
  • dotnet run

C# 7 has arrived... you no longer need to write this kind of madness:
static Main(string[] args) {
  thingIamDoing.RunAsync().GetAwaiter().GetResult(); 
}

instead:
public static async Task Main(string[] args)
{
   await thingIamDoing();
}
pleasing... but a caveat - you must specify LangVersion  in the csproj as latest to use this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>
</Project>

nuget is yesterdays news... stop using it along with package.config.

instead:
dotnet add package EPPlus.Core
also pleasing... especially as it automatically adds the reference to the csproj:
<ItemGroup> <PackageReference Include="EPPlus.Core" Version="1.5.4" /> </ItemGroup> </Project>

so long package.config

So now I have a library to help me read an xlsx file we can experiment. Can this library tell me how many columns and rows there are?

using System.IO; using System.Text; using System.Threading.Tasks; using OfficeOpenXml; ...
var sFileName = @"test_file.xlsx";
FileInfo file = new FileInfo(Path.Combine("C:\\", sFileName));
var sb = new StringBuilder();

try
{
  using (ExcelPackage package = new ExcelPackage(file))
  {
    ExcelWorksheet worksheet = package.Workbook.Worksheets[4];
    var rowCount = worksheet.Dimension.Rows;
    var colCount = worksheet.Dimension.Columns;
    sb.Append($"{colCount} rows: {rowCount}");
  }
} catch (Exception ex) {
  sb.Append($"An error occurred while importing. {ex.Message}");
}

Console.WriteLine(sb.ToString());

This gives me a result of 13 and 55 rows, which is what I expected.
Interesting to note:

  • The API is not zero based, in the example test_file, there really are 4 worksheets
  • If the excel spreadsheet is open, expect a file IO/lock error

Now I know the number of columns and rows we can simply iterate through the spreadsheet to read the data. e.g.

var headerPrefix = "headerPrefix_";

if (hasHeader) {
  headerPrefix = worksheet.Cells[1, col].Value.ToString();
}

for (int row = hasHeader ? 2 : 1; row <= rowCount; row++)
{
  if (worksheet.Cells[row, col].Value == null) continue;
  var newValue = worksheet.Cells[row, col].Value.ToString();
  
  

To export:

string fileName = @"results.xlsx";
var exportfile = new FileInfo(Path.Combine("C:\\Code\\", fileName));

if (exportfile.Exists)
{
  exportfile.Delete();
  exportfile = new FileInfo(Path.Combine("C:\\Code\\", fileName));
}

using (ExcelPackage package = new ExcelPackage(exportfile))
{
  var worksheet = package.Workbook.Worksheets.Add("results");
  worksheet.Cells[1, 1].Value = "Column 1";

  // continue on to fill out row data things here ....
  // once complete - save
  package.Save();
}

Monday, 5 August 2019

React: Key learning touch points

React itself is a powerful framework including a number of key techniques:
Redux:
  • Saga's versus thunks... or both?
  • Global versus local state... are you over-using redux?
Other learning:
  • Remember that setState() can also take a function as a parameter:
  • this.setState((prevState, props) => ({ ...prevState, answer}));
  • setState() is asynchronous, if you call it in the component you cannot guarantee that local state has been updated immediately

Wednesday, 1 May 2019

React: overkill with Redux and where Portals save the day



Recently I encountered a situation where I needed to overlay a div on top of another div. The standard way to do this is to use CSS and absolute or fixed positioning (https://stackoverflow.com/questions/2941189/how-to-overlay-one-div-over-another-div).

Sounds simple enough, however I need to do this from within a deep hierarchy of elements:

-> Detail Component
  -> Action Bar Component
  -> Items Component: Loop through and display expandable content divs
       -> On Click : overlay a component which is a div containing "expandable content"

The "items" component uses a standard bootstrap table to align the elements like so:
item 1 item 2
item 3 item 4

This layout means that when you select the onClick() for "item 1" and you render the expandable component which is essentially just a div, and it is positioned relatively the the content will appear in place of item one in the table.
item 1
(expandable content)
item 2
item 3item 4


Cut a long story short, every which way I tried to style the popup unwanted styles would be inherited from the table and other components above it. I also found that I had to place it absolutely to get the effect I was looking for which created a raft of further problems. Finally, it was suggested that this might be a good use case for React Portals which did indeed save the day.

I also learned on this project how much Redux can be over utilized. "When you have a hammer, everything starts to look like a nail". This was said a lot, and it should be, because when you are deep into the detail of a project it can be hard to see that it has been over-engineered.

Monday, 6 August 2018

Angular Progressive Web Apps

When in doubt refer to the Offical docs. When that doesn't work - try this manual fix it like I did!

Issues with Angular-cli

First it turns out that using ng add, as below, doesn't work very well.

ng add @angular/pwa --project project_name

I thought that maybe these issues were due a change in the Angular app file hierarchy (I changed "src" to "web"). I don't think this was the problem because many other people got stuck on the same error here and here.

Error highlighted below:
Installing packages for tooling via npm.
+ @angular/pwa@0.7.2
added 2 packages in 12.443s
Installed packages for tooling via npm.
Path "/ngsw-config.json" already exist.
I was able to get going by looking to see what this process is suppose to do.

Luckily it doesn't do a great deal and it is possible to find the files by searching your node_module directory then pasting them in before changing the parameters to suit your project - for example: ngsw-config.json to the code root and manifest.json to the /src directory. 

I was also able to better understand what the process should do by looking closely at this git commit. Notice the process adds:
"buildOptimizer": true,
"serviceWorker": true

to angular.json then adds the manifest.json before referencing it in the index.html:
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#1976d2">

Issues with testing service workers locally (A bad HTTP response code (404) was received when fetching the script)

This is a message you are will most likely see when you are attempting use the angular cli server and PWA. Probably running:

ng serve --prod

This is again a heavily documented issue yet that didn't stop me scratching my head.

ng serve will not run the required service worker compilation only ng build will do that - see.

This article also goes on to explain that only secure origins are allowed for service workers. Please consider whether it is worth the time to get this working too. The chances are that the project will work on a secure, encrypted site already now, if deployed.

Finally, you may get "ngsw.json cannot be found" or "manifest.json cannot be found". This can be remedied in Azure at least by allowing JSON MIME type to be served by the web server. Bear in mind that any other JSON in your dist directory will also be accessible.

<configuration>
    <system.webServer>
        <staticContent>
            <mimeMap fileExtension=".json" mimeType="application/json" />
     </staticContent>
    </system.webServer>
</configuration> 

Is it true that service workers only work with transport layer security (TLS or SSL)

No, you can run locally with a local node instance. You can also run chrome with parameters to tell it to always consider localhost secure if you find issues with that. See the official documentation.

Monday, 19 February 2018

The jump between Angular Material 2 Beta 10 and Material Beta 11+

Having just been through this experience I thought I would share some thoughts to help any other early Angular Material adopters navigate their way to the later Beta's - 11 and 12 as well as the subsequent release candidates.

Change 1
Angular Material no longer can be imported into your project as just one module. You must instead select all of the modules which you intend to use in the project.

Change 2 - seemingly innocuous..
The problem with upgrading between these two versions is that the Md prefix has been changed to Mat. This unfortunately now clashes with the AngularJS Material implementation... such as Md2.

We were early adopters of Angular Material, so we are still using Md2 by Promact. Originally this was used as a stopgap while essential components like the date-picker were being completed by the official Angular Material team. However, now, we wish to use both Md2 and Angular Material side by side. Especially since I was originally putting together the project with Angular 4.0.1 and now wish to upgrade to the latest.

ERROR Error: Uncaught (in promise): Error: The "mat-" prefix cannot be used in ng-material v1 compatibility mode.

To get around this you must use the "CompatibilityModule" or "NoConflictStyleCompatibilityMode" or something...?
use compatibility module if you still want to use md- prefix like this
import { CompatibilityModule } from '@angular/material';
and import it in app module
if you want to use new mat- prefix which is good you can
use NoConflictStyleCompatibilityMode like this
import {NoConflictStyleCompatibilityMode} from '@angular/material';
When I first read this comment I was still confused. I just want my solution to work - what is all this!? This comment further down these thread helped me to understand:

Issue 1 thread
Issue 2 thread and relevent comment

I tried importing from material itself but this did not clear the errors.

import { NoConflictStyleCompatibilityMode } from '@angular/material';

Instead the solution seems to be to import and therefore invoke the NoConflictStleCompatibilityMode from MD2.
import { Md2Module, NoConflictStyleCompatibilityMode } from 'md2';

This makes sense because the use of mat in an angular/material v1 context can no only be in the MD2 project.

Wednesday, 12 April 2017

Checking Out React

I started my journey at the React Tutorial Page. While reading the introduction and checking out the code example on Codepen, I then had the notion that seeing as it was a Tic-Tac-Toe game, it might be nice to do it more properly and include it on my website.

Once down this road I then decided it would be good to turn it into a mini project to find out more about yarn and webpack, as these compliment the React world and are the shiny new toys in front-end web development.

This first blog in the series is about the setup.

Notes on Yarn and WebPack
I have heard that Yarn is better than NPM as a package manager, it is faster and more reliable. Webpack is more complex/flexible than Grunt or Gulp as a builder tool but, like my personal favourite JSPM (through systemJS) it is an excellent JavaScript module loader out of the box. Webpack is much more popular than JSPM within the React community.

Back to Tick-Tac-Toe
So I used npm to install yarn, ran yarn init and then used it to bring down my dependencies React and React DOM. I was pleased to find that there is no difference in where the modules are stored - it is still in a folder called "node_modules". I was also aware that I needed to "transpile" the ES2015 React code into ES5 so I installed babel using the "webpack" option on the babel installation page.
npm install --save-dev babel-loader babel-core
Notice that this is based on npm, but this was no problem, you can just replace "npm install" with "yarn add" and the command "--save-dev" with "-D". This was all easy to find here.

Using Webpack to transpile ES2015 back down to ES5
After some research I have found that the best way to use Webpack with babel, karma and react is to use the following packages:



With this setup I was able to setup a simple "hello world" example. I will get into more detail with my next post.

Thursday, 9 March 2017

Windows Azure and Node - Remember to specify the version

I kept finding that my back end code would subtly fail on something once deployed to an Azure site despite working fine in my own environment. Having hit the problem again recently, I again looked through the server logs to try to identify the problem assuming that again Node would be throwing an error over some very simple syntax.

Then I noticed the following:

"The package.json file does not specify node.js engine version constraints"
"The node.js application will run with the default node.js version 0.10.32"

This is old, in fact to put this into perspective the contemporary node change logs start from 0.12.0 which is the beginning of 2015. I had to go through their archive to find out where this version is from, which is October 2014!

Now I know, the solution is to specify the node engine that Windows Azure should use. e.g.


As soon as I had made this change my problems went away as you may expect. Looking at the latest "how to" guide on the Azure website for node development I notice that this features at step 5. However, for those who have legacy node websites on Azure, this is not so intuitive.

Saturday, 19 November 2016

Isomorphic or Universal Javascript

Why I have decided to learn about this?
I first truly took note of the term "Isomorphic JavaScript" when a recruiter sent me through a job which I thought looked extremely interesting. At the time I was not looking for a job, but it reminded me about the long standing problem with decent SEO and Single Page Applications (SPAs). I had heard a lot about React and Angular 2 providing some way to solve the problem, so I was curious.

Notably, the company in question were listing some other design patterns and technologies which were new to me and were also of interest: 12 factor app, Mesos and MarathonCircleCI.

Godammit man, what does Isomorphic mean!
Isomorphic means "corresponding or similar in form". So essentially we are describing some sort of server side rendering to support the client side application.

Or as the AngularJS Universal Repository puts it: "A JavaScript Application that runs in more environments than just the browser".

The advantages?
  • The application does not need to rely on JavaScript being turned on in the browser for it to function
  • The application does not need to have a loading gif to explain to the user that patience is required
  • THE BIG ONE - The application can be more easily crawled by search engines because the page is also available from a static URL.
Some disadvantages and limitations
  • "Uncanny valley" - this is a term used to describe the time between the application appearing to be functioning and available and the time before it is actually responding to the users demands. This can be confusing for the user.
  • Loss of separation between back-end and front-end application code. However, I would say, in this API/ Micro-service architecture world, that this actually makes quite a bit of sense. The User Interface will still be separated from Business Logic, we are just blurring the line between server-side "Get" request responses and view rendering.
  • This is still just a bootstrapping technique and some SEO issues do still remain.
For a more thorough discussion on why Isomorphic JavaScript is "not the answer" take a look at this discussion on ycombinator (at your own risk of course!).

Sunday, 24 July 2016

Karma Error: You need to include some adapter that implements __karma__.start method






An error message which means very little. Something has gone wrong with Karma and it is affecting mine!

It looks like some breaking changes made in Karma-Runner 1.0.0 have really screwed over all the plugin projects such as Karma-Jasmine which I very much rely upon.

The only way around it at the moment is to downgrade Karma to 0.13.22 until Karma-Jasmine is compatible with v1.x.x versions of Karma.



v1.0.0

@dignifiedquire dignifiedquire released this on Jun 23

BREAKING CHANGES

  • context: Our context.html and debug.html structures have changed to lean on context.js anddebug.js. This is in preparation for deeper context.js changes in #1984.
As a result, all customContextFile and customDebugFile options much update their format
to match this new format.



Hmm clear as mud huh?

Certainly I will be keeping a close eye on this issue to see when I can upgrade safely.

UPDATE: It looks as though this has been fixed - all the errors related to this were consolidated in issue 2194 and released just days after I wrote this post.

Sunday, 26 June 2016

Hitting a bug where the best fix is to update... everything

Background

I have been working on a number of MEAN stack projects for the last year and a half. I had been moving rapidly between one project and the next, however, since December last year I have been working consistently on the same ambitious web application.

I have been so focused on delivering new features that I have not been updating my packages at all.

This finally came to a head when trying to improve my production build process.

I was trying to use the gulp-jspm plugin to allow me more control over my JSPM bundled front end JavaScript. Until now I have been using some hacky powershell to bundle my transpiled JavaScript - not the best for adding in more processes into my production build.

Starting Out

After hitting a few minor hurdles I was successfully generating a bundled file through gulp. Hwever when I loaded the application in my test of production mode locally I was getting a "System is not defined error" in the console.

After reading up on the "System is not defined error", it seems that this was fixed at the back end of last year, just when I stopped updating everything. So, time to commit what I have and then head full tilt into the world of updating third party packages...

NPM Tip

There is a command in NPM which tells you exactly which packages are out of date:

npm outdated


This was a useful starting point to try to evaluate how many of the modules needed to be updated and how badly out of date they were. Luckily most of the most crucial babel packages for node seemed to update fine.

Unlinked and operation not permitted ??

When trying to update the JSPM modules, in particular Angular ones with numerous links to one another. I got a number of confusing "please unlink" messages. It seems that this is JSPM's way of moaning about version inter dependencies. The way through this seems to be to remove the main files like Angular and reinstall which sucks, but got me through to the next set of errors.

After a while I was getting a serious blocker in the form of:

Error: EPERM, operation not permitted

I found a number of more recent posts suggesting to readers that they should use the NodeJS console with administrator permissions. I did try this but sadly the end result was no different to using ConEmu in administrator mode.

I then checked the NodeJS version and noticed that it was somewhat out of date @4.2.2 when the current version of NodeJS stable is @4.4.3. The clue here was again from some historic NodeJS GitHub issues. After updating NodeJS JSPM and NPM package managers started working without me having to manually uninstall and reinstall packages.

I finally got to the end of this mammoth updating spree. I run Gulp to build my JSPM build file which was where I was getting the "System is not defined error". The same problem remains. It turns out that the only issue was me misunderstanding the "self executing file" concept in JSPM.

There are three options with JSPM. Either you can generate a self executing file which includes everything that your program needs, including System.js and a "micro-loader". You can create a bundle which must be called by your html - and therefore you must make the node_modules location available. The third option is a full HTTP2 SPDY implementation which seems overkill for me at this moment in time.

The solution was to change the following in my Gulpfile to generate the self executing version:

gulp.task("default", function() {
    gulp.src("sysadmin/main.js")
        .pipe(gulp_jspm({verbose: false, selfExecutingBundle: true}))
        .pipe(rename("build.js"))
        .pipe(gulp.dest("sysadmin/dist"));
});
I have to be philosophical I guess, this blog post might well have the same outcome in my mind as the EU referendum but its a good lesson in why it is important to keep software dependencies up to date, it can lead to a lack of confidence which ends up wasting time.

Friday, 1 April 2016

Setting up Karma to play nice with JSPM

The TL;DR version

I was getting quite frustrated with unit testing today because when I was attempting to use ES6 features like Array.find I was greeted with errors like this one.

TypeError: undefined is not a constructor (evaluating 'categories.find(function (cat) {
                                return cat._id === id;
                            })') (line 19)


I noticed I was also getting a message like this in my stack trace:

tryCatchReject (http://localhost:9876/base/jspm_packages/system-polyfills.src.js

Why couldn't SystemJS load polyfills? It was managing it fine in my browser, at least that is what I assumed.

I made a mistake and thought that I must need to pre-process my unit tests so that they become babelified or ES6 ified or JS2015 ified etc...

I started looking at this...
https://github.com/babel/karma-babel-preprocessor
This made it worse because I was trying to re-implement using a different tool the same task which is being undertaken by JSPM and SystemJS.

In the end the answer was rather than keep adding configuration, strip out configuration and then add just one extra line.

I actually found this tip/clue from the karma-babel-preprocessor configuration page.

Polyfill

If you need polyfill, make sure to include it in files.
npm install babel-polyfill --save-dev
module.exports = function (config) {
  config.set({
    files: [
      'node_modules/babel-polyfill/dist/polyfill.js',
      // ...
    ],
    // ...
  });
});
I added the line above to the files array and "hey presto" all my unit tests were working fine with array.find. To prove that "karma-babel-preprocessor" was not needed I uninstalled it and re-ran my tests.

I later found that I also needed to reference babels polyfill.js in the client-side code that was using the find method.

The only reason I had not noticed was because Chrome has a native implementation. However MS Edge and all other IE browsers do not, so nothing worked on those browsers - a dead giveaway. I added this line to the files in question:
import "babel-polyfill";
See: https://babeljs.io/docs/usage/polyfill/

I found later that sometimes the unit tests would still crash PhantomJS. The final solution to this was to split the specification files from the implementation files using the following from karm-jspm:

jspm: {
    loadFiles: ['test/**/*.js'],
    serveFiles: ['src/**/*.js']
}

The theory being that you don't need to load the actual files to be tested until you have initially loaded the tests themselves.

I think it is fair to say that sometimes Karma does not like to play nicely with JSPM, although this does seem to depend on your project structure as well. I hope these little tips either help to resolve an issue or go someway to alleviate some confusion.

Friday, 11 March 2016

The dev-ops cycle (a tale from the trenches)

Hi, I would like to describe to you a problem which caused real pain for me and the company I work for. And then I would like to explain to you why these problems were occurring and how we kept failing to address them. And finally what was improved as a result.

Some Background (Windows Workflow)

At company x we have been using Microsoft's Windows Workflow Foundation hosted and scaled using a number of Azure Web Instances. In other words, when there is a problem with the workflows it adversely effects the end users. Pretty flawed design, but this is what we had been working with for sometime.

In general Windows Workflow is a highly effective way to manage software development. It offers a clear overview of a highly complex systems and a highly scalable run-time engine out of the box. This guy (Blake Helms) is a major fan and so is the CTO at my company.

Of course, Windows Workflow does have some peculiarities. See these excellent posts on the dreaded tight loop and managing the workflow persistence store.

A Case Study

On Thursday afternoon our web instances started bouncing wildly between 50% -100% CPU usage, our users were complaining that the site was "slow", and restarting one web instance at a time was only solving the problem temporarily. Looking through the logs it seemed that this had been going for a few days to a lesser or greater extent depending on load. The same pattern was occurring again and again each day getting worse and more noticeable - the overall CPU usage would ramp up and then ramp back down again temporarily disabling Web Instances.

Having spent some time looking at this with our normal analysis techniques it seemed that there was no problem with the workflows. Looking at the workflows coming in every couple of minutes showed that they were being processed as expected. I suggested that we see what happens when the users log off at the end of the day - hoping that we would see a clearer picture out of hours.

Accept The Problem

Dev-ops problems tend to be unpopular in organisations. Most people dislike being disturbed of course, but it is also the stress and fraught nature of such incidents which cause Developers to shy away.

I personally believe that there are huge incentives to take on real live problems, but to reap the benefits they must be seen through from start to finish. Like many things in computer science, when a problem is hard do more of it! This, I guess, is why we are seeing more developers become dev-op specialists.

The Danger

The danger with all dev-ops is that we spot the problems and find a work-around, because this gets the situation off our backs.

This behaviour can create the "dev-ops infinite loop" because the real source of the problem isn't fed back into the development process.

As I am writing this now, it sounds obvious: find the issue and make sure there is a pull request into the next release which fixes it, what's the problem?

Well, it is quite possible that you may not have considered where or how the situation came about from the very beginning. In larger organisations a particular release may have involved many people, which could mean that vital information is lost or unavailable to you. It could also be that information may have been forgotten completely due to a release cycle that is too long or too complex.

Understanding Why - Continuing The Case Study

By Friday team was starting to get desperate because the problem was not going away and we still could not understand why the problem was happening. There seemed to be no difference between out of ours and in hours. A few theories were put forward with minor bug fixes in the code, one of which was a bug which had been present in the system since nearly the first release, lets call this "Theory 1":


  • Email templates are being compiled through the Razor engine every time an email is sent. This causes the CPU usage on the Web Instance to ramp up because it is such a resource heavy operation.


If you have worked with Razor in a highly scaled system, you may have also come across this problem. A fix was developed and released over the weekend. The email Razor templates would now be pre-compiled on app startup thus reducing the load and solving the problem.

However, come Monday morning this did not calm the server instances down. Every time we ran up a new server instance the load would be OK for a time but then would start bouncing up and down giving our users a poor experience when using the site.

A Moment Of Monday Clarity

"Theory 2":

  • There is a workflow which is running which is blocking the web instance and causing the increase in CPU usage.

We had to accept on Monday that it was back to the drawing board. The workflows had been disregarded as a potential cause because the monitoring tools we had written to check the database showed that the workflows were being processed very efficiently. However, there seemed to be no other plausible explanation.

Further analysis on the "workflow instance table" in the database showed us that there were a growing number of workflows being fired of a particular type at very particular intervals. We were able to identify this by changing our workflow monitoring tools to look at the number of workflows queued of a particular type, rather than how many workflows were suspended or overdue.

The Temporary Fix

On Monday evening we were able to push a small fix which restricted the workflow in question so that it ran only in out of office hours. We hoped this would get the users and the CEO off our backs - yes it got pretty serious! But we were still not entirely clear on what the route cause of the problem was.

Finding A Lasting Solution

The final solution to the problem was eventually deduced through some more thorough detective work. The kind of detective work that is hard to do properly when under pressure.

What went into the last release that could be very resource hungry? And what could cause this hunger to increase gradually over the days that proceeded afterwards?

The answer turned out to be from a new more generic workflow which had been written to replace a number of other workflow processes. There was actually nothing wrong with what the workflow was doing. The only error that the developer had made was to fail to consider its impact when deployed "en masse" if you will. This workflow had been written by a developer who had left the company some months before. Something like this would have been tricky to predict.

Areas For Improvement

I would say that this tale lays bare some quite common problems within software organisations.

  • Before the software was released, there was no effort made to load test the solution.
  • When the release was promoted to production, there were so many changes made by so many developers over so much time that there was no "scrum master" or technical leader who knew enough about what was in the release.
  • After the release was running, the tools for monitoring the solution where not sensitive or sophisticated enough to show a larger than expected increase in server resource usage.
  • The problem went unnoticed for too long.
  • When the problem was identified, developers hoped that it would just "go away" without pursuing the problem vigorously enough.
  • Developers put too much faith in one solution working without thinking enough about developing some ideas on other solutions.
  • Nobody in the team was calm enough to look through the new feature list and suggest a feature with risks.

What has happened since this incident:
  • UAT goes through a load test before being promoted to Production.
  • Releases are kept much smaller and more frequent
  • The workflow database monitoring tools have been improved
  • We gave ourselves a kick and tried to learn as much as we can from the case.
  • The incident resolution process has been looked at.


Getting started with Python...in Windows 10

Python is increasingly popular
The testing team where I work are using it in a big way to run automation scripts. It seems to be the language of choice to teach to 17 and 18 year old's at A-Level. I was recently forced to admit that I had never written a single line of code in Python... time to change that!

Getting started
Full of enthusiasm I went to the beginners guide on the Python Wiki . Immediately there seems to have be a break in the development of the language. In 2010 Python 3 was released and it looks like some want to hang on to Python 2. Did it really break that badly? Honestly I don't know the history but it makes for a baffling first impression. Looking around it seems that somebody is recommending Python 3 for learning and then you can go back to v2... erm no thanks! Sounds terrible, I'll stick to 3. I later found the Python 2 clock, there is a  rough deprecation deadline for Python 2.7 in 2020.

Ok, so it looks like JetBrains have made a super cool IDE with a free download... oh I have to pay for this after the 30 day trial. Hmph! Not very friendly for a beginner. I thought this was a script kiddies language?

This is more like it. Now all I have to do is download the web based installer - it asks me whether I want to install Python to the Windows Path, I think yes. In the latest installer, it is not set by default so watch out for this option.

Setup successful and a nice link to the docs. Now we are getting somewhere. I then fire up my Powershell console of choice and type "python". Thanks to ticking the install to Windows Path option this works.

Now lets do the standard Hello World app. In Python 2 you would write:
print "hello world!"

In Python 3 its:

print("hello world!")

Confusing huh!

I will continue this tutorial with next time I write. I will demonstrate how to define the structures that underpin the language.