Custom expiry times for Mongoose documents in Node.js

10 Sep

If you’re using MongoDB and Mongoose in your Node.js application, perhaps on IBM Bluemix, you may need to expire (delete) documents documents at a set time.

The Mongoose documentation includes instructions for creation of a schema-level expiry time, with all documents expiring a set number of seconds after their creation.

However, it doesn’t explain how to specify a specific expiry time for an individual document.

Here’s a snippet of how to do this:

var mongoose = require('mongoose');

// Define our token schema
var ThingSchema = new mongoose.Schema({
	value: {
		type: String, 
		required: true
	},
	expireAt: {
		type: Date,
		required: true
	}
});

// Expire at the time indicated by the expireAt field
ThingSchema.index({ expireAt: 1 }, { expireAfterSeconds : 0 });

var model = mongoose.Model('Thing', ThingSchema);

You can set validation and defaults on the expireAt field, too:

	expireAt: {
		type: Date,
		validate: [ function(v) {
			return (v - new Date()) <= 60000;
		}, 'Cannot expire more than 60 seconds in the future.' ],
		default: function() {
			// 60 seconds from now
			return new Date(new Date().valueOf() + 60000);
		}
	}

One gotcha – the MongoDB expiry reaper only runs once a minute. This means a document could remain in the DB up to 60 seconds after it has expired. You should write your code to allow for this.

Where do I specify the hostname of my Worklight server?

26 May

When developing a Worklight application, there are various places the hostname of your Worklight server might need to be specified, and might end up:

  • In the mobile app itself (the .ipa, .apk etc.) – this value (prior to Worklight V6) was taken from the application-descriptor.xml file during the build of the application and determines where the app attempts to connect back to for adapter calls and so on. In versions of Worklight subsequent to V6, it is now specified instead in the <app-builder> ANT task (used for automated builds of the application) inside the worklightServerHost property.
  • In the publicWorkLightHostname, publicWorkLightProtocol, and publicWorkLightPort values inside the worklight.properties file. These values determine:
    • Where the Mobile web and desktop browser apps should connect back to.
    • How the Worklight Application Center (if used) will form RESTful URLs for its own internal use.

In all cases, these hostnames should point to the externally-resolvable address of the Worklight server (in front of any load-balancers, firewalls, proxies, etc.).

Thanks to Itay Hindy and Thomas Kw Poon for help with this tip.

Enabling WebView remote debugging in KitKat

26 Feb

My current application is targeting multiple versions of Android, but I’d also like to enable the remote debugging features of KitKat’s new WebView. This creates a problem when trying to maintain API compatibility, as the methods to enable debugging don’t exist on older versions of Android.

Here’s the snippet of code I’m now using to get around this problem – it leverages Java’s reflection API to allow us to enable debugging, but only if it’s available on the platform. Make sure you augment your Android application’s main Java file correctly.

public class CustomerView extends WLDroidGap {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);		
        
        // Enable remote debugging, if available! - KitKat or more
        if (Build.VERSION.SDK_INT >= 19) {
            if (0 != (getApplicationInfo().flags = ApplicationInfo.FLAG_DEBUGGABLE)) {
                try {
                    Method m = WebView.class.getMethod("setWebContentsDebuggingEnabled", boolean.class);
                    m.invoke(null, true);
                } catch (Exception e) {
                    // Oh well
                }
            }
        }
    }
    
}

How to make your generated widget’s DOM IDs reflect their AMD module

14 Nov

In the new AMD world, it’s suggested that we omit the specification of a “declaredClass” in our custom widget’s declare() call, like so:

define(["dijit/_WidgetBase"], function(_WidgetBase) {
    return declare([_WidgetBase], { 

    })
});

However, in this case, _WidgetBase doesn’t have a specified value for declaredClass, and uses the declaredClass from an appropriate parent class to automatically generate a DOM ID.

I’ve worked around this so far by using a pattern like this:

define(["module", "dijit/_WidgetBase"], function(module, _WidgetBase) {
    return declare(module.id, [_WidgetBase], { 

    })
});

Hopefully we’ll see some fixes from Dojo here to make this easier in future.

Destroy all widgets/dijits in a DOM node

31 Oct

Following up on Tom’s post from 2011, and taking into account the comments posted, here is the latest “known good” technique.

Often we need to empty a DOM node of all widgets. Here’s the magic incantation.

require(["dijit/registry", "dojo/dom-construct", 
        "dojo/_base/array"], 
        function(registry, domConstruct, array) {

    // Your DOM node reference goes here
    var node = null; 

    // Destroy the widgets, including their
    // children and DOM fragments
    array.forEach(registry.findWidgets(node), 
        "item.destroyRecursive()");

    // OPTIONAL: Explicitly empty the node.
    // This will take care of DOM nodes that 
    // weren't managed by widgets
    domConstruct.empty(node);

});

dojox/mobile :: Programmatic View transitions

28 Oct

When programmatically initiating View transitions, we have two choices. Given the following markup, we can initiate a transition between view1 and view2 in two ways.

<div data-dojo-type="dojox/mobile/View" id="view1" selected="true">
   stuff
</div>
<div data-dojo-type="dojox/mobile/View" id="view2">
    more stuff
</div>

Option 1: View.performTransition()

dijit.registry.byId("view1").performTransition("view2", 1, "slide");

See the dojox/mobile/View API for full details.

Option 2: new TransitionEvent().dispatch()

require(["dojox/mobile/TransitionEvent"], function(TransitionEvent) {
    var view1 = dijit.registry.byId("view1");
    new TransitionEvent(view1.domNode, {
        moveTo: "view2",
        transition: "slide",
        transitionDir: 1
    }).dispatch();
});

See the dojox/mobile/TransitionEvent API for basic details.
It is possible to write a basic wrapper around this function to simplify your code.

Which to use

Option 1 (View.performTransition) looks simpler, but it does not handle transitioning to nested views correctly in some cases, leaving ancestor views invisible.

Option 2 (new TransitionEvent) is recommended. It handles these edge cases correctly, establishing the correct “from” and “to” views, and ensuring ancestor views are visible.

Worklight 6.0 and Dojo integration

14 Oct

The new Dojo tooling in Worklight 6.0 has left a number of people confused. In this post, I’ll explain how the various resources and settings in a new Worklight 6.0 project interact, and how to change these to achieve the desired effect.

Continue reading

Follow

Get every new post delivered to your Inbox.

Join 82 other followers