thiagomajesk

thiagomajesk

Hello everyone! How are you? (I hope you are all fine despite the current situation)

Well, I already spent a good amount of time researching and testing some solutions and I’d like to see if anyone would like to leave a suggestion on other ways to solve this before I make it final.

I’m creating an application for game servers that can interact with the game’s database and enhance the administration experience for community managers.
So, usually, there’s already a database setup in place for those game servers (MySQL 90% of the times) and my application’s database only stores configurations, logs, table references, etc. I have two repositories configured for my application, one that I have control over the schema and the other which I don’t and need to query based on certain conditions.

One of the problems I’m facing right now is coming up with a good strategy to allow the administrators of the server to configure how queries are done against their database and successfully building those queries.

Currently, I’m storing configuration on a table as key/value pairs, and the user can set, for instance, the name of specific tables to be retrieved, primary keys (for cross-referencing) and which fields of a given table can be selected (like player rankings, etc).

Most of this configuration is saved as ‘string’ and Ecto, as far as my research went, only accepts ‘atom’ fields, so this requires me to at least convert these strings to atoms on the fly (which I discovered is not recommended).

A simple example would be retrieving a player from a table and only returning specific columns:

# Configs retrieved from the database
accounts_table = "accounts"
account_columns = "id, player_name, registration_date"
username_column = "player_name"

# Something to query
username_list = ["alpha", "bravo", "charlie"]

#
# Convert some of the string values before passing to the query (account_columns, username_column)
#

GameDatabaseRepo.all(
    from a in accounts_table,
    where: fragment("? in (?)", field(a, ^username_column), ^username_list),
    select: ^account_columns
)

One of the things I’m doing to prevent creating a lot of atoms is to limit the number of columns the user can specify, but I’m not completely happy with the solution so far because it is a very poor workaround.
I also tested storing the queries directly to the database and just including filters, but the fragment function does not play nice with only string params (SQL injection reasons).
I also tried running raw queries and setting SQL variables as an extension point but I lose a bit of composability and SQL variables have their own set of limitations.

Showing Posts 1 to 10

al2o3cr

al2o3cr

If you’re looking to provide an interface for reporting-style queries, have you considered systems like Metabase or Elasticsearch?

For instance, the Elasticsearch Query DSL seems like a vastly-evolved version of what you’re sketching.

thiagomajesk

thiagomajesk OP

Hey @al2o3cr! Thanks for the reply.
Unfortunately, MySQL is a hard requirement (I don’t have control over that). Another thing is that I’m not always retrieving data, I might need to insert it (directly) and because of that, I’m dependending on the game’s database.

michallepicki

michallepicki

Maybe you can use String.to_existing_atom/1 and handle ArgumentError accordingly

thiagomajesk

thiagomajesk OP

I thought of that as a safer alternative and I’ll probably use that to increase safety, but those game databases are huge. Think of hundreds of columns for hundreds of tables (I’d prefer if Ecto was not strict about atom fields when you don’t have control over the schema).

al2o3cr

al2o3cr

Both Metabase and Elasticsearch are secondary indexes - you’d typically configure them so that changes in the “main” database are pushed to them.

Be very wary of this practice - it’s essentially treating the entire hundreds-of-tables game database as a public API. If the game doesn’t provide a real API, I recommend you write a narrowly-focused one that writes to the things you need and use that instead of sprinkling random INSERTs throughout your code.

IMO this friction is a sign that you’re working against the grain of the tool; Ecto is primarily designed to handle building SQL queries that are known at compile time, and that’s the opposite of what you’re building.

I’m curious about the exact sort of users you’re envisioning for this; there’s a very narrow window of skill between “can understand a schema with hundreds of tables well enough to query it” and “can write SQL”, and the abstraction you’ve described doesn’t remove very much complexity.

thiagomajesk

thiagomajesk OP

I know, I know, I’ve worked with Elasticsearch before…
The problem is that this is not a greenfield project, there are very restrictive constraints in place. I can’t for example, impose an Elasticsearch cluster because it’s beyond the budget. Dedicated game servers are already too costly and most of the time the person behind it is not an expert to deal with a lot of ‘moving parts’.

Yes, it’s not ideal, but usually, this is a tradeoff the server administrator is willing to accept for better management because the game source code is not extendable or moddable enough.

It’s not about removing complexity per se, it’s about extending something that can’t be extended by the ordinary means. I’m gonna give you a hypothetical (but realistic) scenario:

Have you heard of a game called Legends of Aria? If not, the thing you should know is that this game allows creators to build their own rules on top of the base game. So I could, for example, host the game with my own set of rules (which I modified from the game tools). This way, any player that bought the game can enter the official server or my custom server.

Most of the time, those kinda games have tools that are closed source (except for some rare exceptions where the game is extendable to the core - looking at your Minecraft).
Because of that, we only have access to the database as an extension point. If I want to have a website that shows player data or an auction house or even sell cosmetic items, and the game tooling does not support that, the only way is to query and insert data directly to the database.
And then, there’s the fact that most of those games are built in completely different ways, so this has to be configurable by whoever is administrating the server. So far I’ve come to realize It’s a very unique problem.

ardhitama

ardhitama

Not really a solution, but ecto dsl mostly are macros, have you tried to replace that with yours?

eg. accepting strings then do some validation?

michallepicki

michallepicki

I am still trying to understand the problem, so I am guessing that even if you don’t have control over the data schema, the data schema doesn’t change, right? There’s no way the games let users add tables or columns, right? So the problem you have is with making it easier to integrate with various schemas. Maybe you could look into providing a database introspection tool that would generate the configuration? Then create ecto schemas on the fly based on that config

edit: Or even not generate schemas, just use schemaless queries but you’d have the information needed to properly handle columns and their types. I have done a similar thing recently where I have general where functions that use the field(t, ^col) trick and I use the column type information to cast the string input to appriopriate types before calling them

thiagomajesk

thiagomajesk OP

Interesting :thinking:.
I’m definitely check this out, thanks for the suggestion @ardhitama!

thiagomajesk

thiagomajesk OP

The schema might be different, and that’s why it has to be configurable. Perhaps there’s a column called ‘username’ in a ‘users’ table instead of a column called ‘login’ in a ‘accounts’ table - it depends on the game or the version if we are talking about the same game, but usually, there are some similarities, the administrator of the platform has to hint this out to the system.

Something like this lib?
One thing is that it has to be configured at runtime, so I’m not sure.

This is what I’m doing right now, hence the problem with field atoms that I’ve mentioned.
I’m also very inclined to start running raw parameterized queries to avoid hitting limitations with Ecto.

Very interesting suggestions to consider so far.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews