Sunday, October 27, 2013

TiledStack Update - Server persistence, Web development and Hosting

In the past week or so I have been doing a bit more work on 'TiledStack', specifically web, server persistence of map changes and user management.

I have also been updating the 2 clients main clients. The MonoGame client (AKA, run-time client) and the file watcher client which looks at changes in the local tiled file and generates requests to the server (collaboration client).

Server Persistence

After working with MongoDB for the persistence layer, I hit quite a number of issues which I thought I might go through in case they might be useful to some one else who might be looking to use it. Originally I was saving the JSON structure that Tiled spits out from saving a map to a JSON file. Which looks like this. I was storing this as one document in MongoDB and due to the way the collaboration client picks up changes in a map and sends off requests, an 'objectgroup' could be updated with many requests in a single change. Eg, the map creator has just moved 3 map objects, delete 2 others and created a new one in one object layer, this would fire off all 6 async requests to the server.

This is where I found MongoDB couldn't work for what I needed. Concurrent updates to sub-elements and even sub arrays did work (for add and delete, update I couldn't get to work) using $.pull and $.push, but these functions were unable to be used on arrays any deeper than the first child on the document. Eg, Map->Layers could be updated via these functions (Layers being an array), but MapObjects which was potentially an array in each Layer, was unable to use $.pull etc unless I already knew which index I wanted to update. As soon as I need to pull documents into server memory due to the lack of functionality of a database, I have concurrency issues.

MongoDB is really easy to get going, and to it's credit is really fast, but I think is lacking functionality for more complex situations. It almost seems that they are making concessions with how some of their query syntax works to make sure it's fast in 90% of situations and just missing in the other 10%. In summary/TLDR.
  1. Some functionality only works for first/second level of child elements
  2. Good for heavy read, light write (write once) situations
  3. Hard to update complex documents

PostgreSQL

After spending too much time trying to get around these short comings, I finally decided to move to another DB. I briefly looked at other NoSQL databases and came to the conclusion that relational is a simpler way forward for now. This was my first time using PostgreSQL, however again thanks to ServiceStack and more specifically ORMLite for .NET which is a part of the stack, I was able to quickly re-implement my repository interface and get up and running.

One concession I did have to make (however had already made to try and get around issues with MongoDB) is to have one data structure for persistence and another that represented the Tiled map common to both client and server. These structures are thankfully very similar, just replacing class references with foreign keys to relevant table.

After a quick test generating a few hundred async requests, everything worked nicely, although slower, much easier to work with and data is stored as expected.

Web

One of the things on my todo list was to create a web interface where other developers/users could have a site to share maps, tilesets and use the hosted services to help them work on a game, perhaps with a distributed team. First thing I need to do is have a way for people to sign up. Currently only have Google OpenID integrated for user management, but it's a start and currently building the 'manage maps' functionality so users will be able to manually upload there maps to share if they don't want to use clients, or want to delete, make private, rename etc. Here's a quick look of what I've got so far.



Built with Bootstrap, AngularJS and ServiceStack (of course) for backing services. More to come.

Amazon Web Services

As a .NET developer, Azure might be the more obvious choice, however I have been interested in using AWS more as part of me dislikes the idea of Visual Studio (2013) adding more and more integration with Azure due to the potential reliance developers will have on it as time goes on. So after getting a couple of VMs (one Windows, one Linux) up and running, I am so far quite impressed with AWS and will continue to use it for this project for now.

Trello

Also, I have made my Trello board for this project public if people are interested in what parts are being worked on. I do try to keep it mostly up to date, but as this is only something I am doing in my spare time, like this blog, will be updated on a random basis. If you haven't used Trello, I highly recommend it! I still haven't used something which matches it on functionality and user experience for project management (or anything else for that matter!)