Me Love You Runtime Code Monkey!

Serverless and Lambda

I’ve been working more with serverless projects using stuff like AWS Lambda or Azure Functions. Very handy indeed: easy to deploy and then use. Sometimes though, you want a little more: you need an S3 bucket or want API Gateway in front of the Lambda function. Enter serverless!

The Serverless Framework allows for easy deployment of your Lambda and other services by just describing your infrastructure in a serverless.yml file. You can define what API Gateway endpoints you need and which Lambdas they can point to, set up a DynamoDB or S3 bucket with permissions. You can then run ‘serverless deploy’ from the project root and it’ll package everything up in a .serverless folder and upload to AWS, setting up a Cloudformation template and running it so you can then tear down the environment. It’s simple and really powerful. If you’re doing any work with Lambdas or AWS Functions, I’d recommend looking into serverless.

Below is an very simple yaml file for serverless. You can set the provider (serverless runs on Azure, AWS, IBM OpenWhisk currently), language version of your code. In environment, this would just read a yml file in the ‘vars’ folder depending on the stage. You can also run

serverless deploy --stage testing

To change the file being used from “dev” - which is set in the stage setting to “testing”. You can exclude files from being packaged up and if you have multiple Lambda functions, you can choose to package them up individually.

At the bottom of the yaml there is an API Gateway endpoint pointing to the Lambda function.

# For full config options, check the docs:
#    docs.serverless.com
service: middleware
provider:
  name: aws
  runtime: nodejs4.3
  stage: dev
  profile: lambda
  region: us-east-1
  environment: ${file(vars/${self:custom.stage}.yml)}
custom:
  stage: "${opt:stage, self:provider.stage}"

package:
   individually: true
exclude:
  - .gitignore
  - .jshintrc
  - .npmignore

functions:
  myfunction:
    handler: functions/myfunction.handler
    events:
      - http:
          path: someendpoint
          method: post
          cors: true

You can even run the Lambda function locally by using invoke local

serverless invoke local: --function myfunction

Which is great for dev testing.

Umbraco Lucene Date Range fun

You know days when you think everything is fine, then you hit a snag and it takes the rest of the day? Yup. That happened today. The issue this time was with an Umbraco implementation I am working on at the moment.

With searching using indexes in Umbraco it’s all rather buggy. DateTimes are stored as the format: yyyyMMddTHH:mm:ss in Lucene when Umbraco indexes. The issue with this is that it stores in Lucene as a string. So when you do a query in Lucene for a date range. It’ll give you some pretty gnarly results. Lucene expects the format: yyyyMMddHHmmss000

The best thing to do is to convert the string before putting in the index. Umbraco has a nifty Interface you can use for this called IApplicationEventHandler. This is automatically hooked up when Umbraco finds it in your assembly.

You can then use the following method to add the custom string in:

public void OnApplicationStarting(UmbracoApplication httpApplication, ApplicationContext applicationContext)
{
	var siteIndexer = ExamineManager.Instance.IndexProviderCollection["IndexerName"];
	siteIndexer.GatheringNodeData += GatheringSiteIndexDataHandler;
}

void GatheringTagIndexDataHandler(object sender, IndexingNodeDataEventArgs e)
{
	var node = new Node(e.NodeId);
	e.Fields.Add("yourdatefield", "your new date string");
}

If you want to override a field already in Lucene, you can just remove it first by using:

e.Fields.Remove("yourfieldname")

Good luck!

Setting up Sitecore on Amazon RDS

This week I have had a bit of a nightmare setting up a client’s site using Amazon’s Relational Database Service (RDS). The issue arises because you can’t just restore a .bak file on RDS as there is no access to the service’s file system. I read a blog post here: http://blog.xcentium.com/2012/06/how-to-install-sitecore-on-aws-using-amazon-rds/. This didn’t really fix any issues and caused errors. I tried scripting the database and it’s data which kind of worked, but caused some data to not work properly, mainly the membership provider.

I looked into Red Gate’s SQL Packager and realised it creates a .net executeable of the full database. Originally I rejected this thinking it would need access to the RDS file system again. How wrong I was. You can just run it and connect to the RDS instance and away it goes. If you’re working on RDS at all with Sitecore, this is a really useful tool.

Replaceable token issue with config ConnectionString transforms

I ran into a little conundrum the other day trying to make a .net C# project build and deploy. I was making a build using MSBuild which also transforms config files. This was all working, but in the config’s ConnectionStrings element, the transform was coming out with:

<add name="Connection" connectionString="$(ReplacableToken_ProjectName-Web.config Connection String_0)" providerName="System.Data.SqlClient" />

Now, I thought that $(ReplacableToken_ part would be properly transformed for the relevant environment like:

<add name="Connection" connectionString="[LiveDB connectionstring]" providerName="System.Data.SqlClient" />

The issue is that MSBuild actually does this on deploy, not on build. It’s a feature. On build, it just creates a placeholder. You can, however, make MSBuild switch the connectionstrings on build by adding the following line of xml into your .csproj file inside the first PropertyGroup:

<AutoParameterizationWebConfigConnectionStrings>
False
</AutoParameterizationWebConfigConnectionStrings>

I’ve only found this for Web config connectionstrings so far, the others seem to just work immediately.

Remove your Webforms ViewEngine for MVC

I learnt something interesting today. When we use MVC and the Razor view engine, we can end up with a bit of a performance hit. In fact, Razor can end up running much slower than Webforms because we don’t clear the Webform view engine (up to half as fast!), so your app will run that view engine first, and only when it fails to find the relevant files will it switch to the Razor view engine. And to get round this, all you do is add the following to your Application_Start method in the Global.asax.

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());

You’re welcome!