TabbycatDebate / tabbycat

Debating tournament tabulation software for British Parliamentary and a variety of two-team parliamentary formats
https://tabbycat.readthedocs.io/
GNU Affero General Public License v3.0
242 stars 816 forks source link

Future: Microservices Architecture #1380

Open prasgema opened 4 years ago

prasgema commented 4 years ago

Hi All,

Yesterday morning, @czlee and I talk about microservices to see whether this is a good fit for the future of tabbycat. Then I remembered on 2016, he mentioned that he wanted to put together all the debating apps that can integrate with tabbycat. Then, I see that what @czlee envisioned was not a super app, but collection of simple apps that has a solid use cases.

Microservice are actually a paradigm that a huge apps (like tabbycat, yes it's huge) should've been divided into multiple smaller apps. For easier code management, separation of labor (people and computing resources), easier scaling when one of our module taking a lot of resource.

General overview: https://blog.newrelic.com/technology/microservices-what-they-are-why-to-use-them/ Architectural pattern: https://microservices.io/patterns/microservices.html

IMO, this is how tabbycat will looks like if the app is divided into microservices:

  1. Authentication
  2. Tournament (conflicts, draw rules, configurations)
  3. Debates Module (rounds, motions, draw, checkins)
  4. Adj Allocation
  5. Scores Module
  6. Feedback Module
  7. Frontend -- which is an empty shell. It needs to connect to backend services to operate

P.S: I intended to put together a diagram soon

prasgema commented 4 years ago

api-gateway-microservices (1)

Microservices on the right. Huge app (Monolithic) on the left.

Don't mind the technical stuff like API gateway caching etc

philipbelesky commented 4 years ago

Hey @prasgema, thanks for your thoughts on the matter. While I agree that in the abstract this kind of architecture would hit the benefits you define, there are a couple of hard constraints here that mean I don't see any viable path to transitioning to this format.

Almost all of our users deploy to Heroku which is a resource-constrained environment, particularly if favouring ease of deploy (1 click) and running on a free tier. Given (to my understanding) microservices are designed to be deployed as independent entities (i.e. a cluster of Docker/Kubernetes instances) that likely violates either ease-of-use or pricing constraints; both of which are probably non-negotiable regressions. Remember that microservices primarily solve problems — scaling, deployment, resilience — that do not apply in the same way when we have decentralised user-run infrastructure. Happy to be wrong here, but I would want to see a demo prototype for how to easily deploy this architecture before considering this viable.

Tabbycat is built atop Django and I don't see any viable way of migrating that backend away from that short of a near-complete rewrite that is definitely not viable. For example, the frontend of Tabbycat is almost entirely detached from Django's templating engine on particular pages — e.g. Edit Adjudications, etc. Providing the end points are made, it could be fully detached on all other pages. However, this is such a massive task with next to no end-user benefit that it has not been attempted and I don't think ever will.

That's not to say that a couple of functions, say feedback or adj allocation, could be split out of the core app. If third-parties develop those functions, if they are easy to setup, and if other tab software utilises them also, then there's a strong case for allowing them to evolve independently and reduce the size of our code base. But that's not a micro-service architecture. In contrast, separating out a Debates Module from a Scores Module within Tabbycat itself would likely add great amounts of complexity and developer headache without having the side-benefit of allowing better third-party integrations.

prasgema commented 4 years ago

I see. You're not wrong here -- pricing, ease and resource constraint are valid concerns.

While I didn't have any solid recommendations yet for how can we do this easily. However, I can show how my team manage microservices; still with free tier: swarm of services However I agree that this is not easy to deploy -- hope i'm wrong.

This might be something that we do far away in the future tho; I would see that may be somewhere in the future, we will be hitting a wall on managing our codebase. The common practice of teams carving out modules (after understanding the reason behind and priorities) are:

  1. build a beta frontend module
  2. build the first backend module to be carved out
  3. deprecate old backend module
  4. repeat step 2 and 3 until we find the right combinations

And btw, when you say:

That's not to say that a couple of functions, say feedback or adj allocation, could be split out of the core app. [...] But that's not a micro-service architecture. [...]

Actually that's how usually people start working on "microservice-ized" apps. They usually start with huge apps, divide them into smaller modules, then divide them into atomized version of those modules to enhance reusability on elementary modules (e.g: authentication, master data)

philipbelesky commented 4 years ago

I think we hit the wall on managing the codebase awhile back :p. Although from the perspective of a maintainer, I'm less concerned about abstraction in the separation-of-concerns sense, and more concerned about complexity in terms of dependencies/frameworks etc. Django's batteries included approach has meant we have a general sense of where and how everything fits together.

Our increasing reliance on Vue has (i.e. step 1) has stretched that a bit — I think I'm the only one with a complete understanding of that system, whereas I think all of the other maintainers have enough familiarity with Django to be able to dig into any part of the backend. This all becomes moot though at the point the modularised systems start to be developed by others though.

Actually that's how usually people start working on "microservice-ized" apps. They usually start with huge apps, divide them into smaller modules, then divide them into atomized version of those modules to enhance reusability on elementary modules (e.g: authentication, master data)

Right. I generally think of the novel part of microservices as being tied to a new approaches to deployment/orchestration like Docker/serverless/etc. A more general approach to pursuing as much modularity as possible (to me) seems like a more standard best practice (within constraints).

Anyway, happy to keep this open as a tracker if you or others would be keen to take on task (1). The API, as it evolves, should make this much more approachable although there are a number of sore points, like forms, which would be tricky.

A great place to start though would be to begin by just spinning off the public-facing pages of a site into a SPA javascript bundle. Those pages would map closely to endpoints in a basic API, and could feasible be deployed as either a separate instance to the backend or alongside it. The former option would likely have great value to high-profile tournament sites and their high traffic loads.

Another less immediately useful project would be to spinoff some of the specialised algorithms — e.g. position balance, draw generation, adjudicator allocation, etc. I would imagine those as libraries, rather than apps, but it would be great to allow those functions to evolve independently of Tabbycat proper.