Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - CultLeader

#1
The pattern V2 / Eden DB Improvements 3
April 27, 2024, 10:29:26 AM
Sup bois, I've added extremely powerful feature into EdenDB: OCaml data modules. What this allows to do is to define data in OCaml using typesafe generated constructs.

I did this a while ago in this commit https://github.com/cultleader777/EdenDB/commit/9270c3e42ab28410e8ba3018f76b4eea0b586da4 , just didn't get around to describing it yet until now.

Motivation? Eden data language is fast to parse but will never be as powerful as standard typesafe programming language.

For instance, if I want to define 10 similar nodes in a cloud, doing it with OCaml is trivial, run a loop and you're done.

People write an utter abominations like jsonnet, or they add hacks like count variable in terraform or for_each in terraform.

In reality we just need a good programming language to define our data and we don't need to learn useless garbage like jsonnet, or how to program in terraform (which is nightmare). Terraform output is just an assembly compiler later, we don't deal with it directly.

Here's an example.

Say, we have main.edl file


DATA MODULE OCAML "some-module"

TABLE test_table {
    id INT PRIMARY KEY,
    some_text TEXT DEFAULT 'hello',
}


And we have OCaml file at some-module/bin/implementation.ml

open! Context
open! Db_types

let define_data () =
  mk_test_table ~id:123 () |> def_test_table;
  mk_test_table ~id:123 ~some_text:"overriden" () |> def_test_table;
  ()


So OCaml allows us to define table data in OCaml. We didn't write mk_test_table function (generated). define_data function is required in the generated code. There's a some_text column that has default value if unspecified. If your OCaml file implementation mismatches schema it's a compile time error.

To someone who's used to the standard implementation of compilers that do very boring stuff, linking executables from explicit outputs this might not be trivial how it works. In fact, I don't recall any compilers that do anything similar to what is done here. If codegen step is performed, it is usually performed in some Makefile task before compilation.

So, this is how it works:
1. EdenDB compiler parses all .edl sources with includes
2. We first process table schema and their interconnections, any error there (non existing foreign key column and etc.) is EdenDB compiler error
3. Now we know all the schema that will be in EdenDB, we just didn't insert any data yet and didn't check foreign keys, constraints and etc.
4. At this point we actually run OCaml codegen for the OCaml data module defined at some-module.
   We generate: dune, dune-projec, context.ml, context.mli, db_types.ml, implementation.mli, main.ml and dummy implementation.ml if it doesn't exist yet.
   User is responsible for modifying implementation.ml file with his data, he can have other OCaml files with utility functions and everything.
   We assume that we use dune for OCaml.
5. Now we insert the EdenDB data that is defined in EDL
6. At this point, EdenDB compiler runs dune exec for data modules, reads json dump of defined data, and inserts data into EdenDB state according to the schemas
7. The rest of EdenDB checks are performed, like checking duplicate primary keys, foreign key existance on all of the data, whether it is defined in EDL, Lua or OCaml

I haven't seen any compiler do something like that so I thought it is interesting design. And I'm 99% sure, being 70k lines of code into Eden platform that this is how I will define my data at the end of the day.

So, Current eden platform pipeline:
1. Run EdenDB compiler, which runs OCaml data modules and defines data of all of our infrastructure. Basic database correctness checks are performed here
2. Eden platform analysis step, here we perform all the checks regarding our infrastructure, say if defined node ip belongs to the DC subnet, that we have 3 or 5 consul servers per DC and so on
3. Codegen step runs which compiles the rest of our project, including provisioning, postgresql migrations, nix configs, and gazillion of other stuff. There are files that user can edit manually in Eden platform in their project directory (mainly business logic of EdenDB applications).

Have a good day bois!
#2
Working on Eden platform (at this point I have AWS and Google cloud talking together, and I did bunch of internal refactorings, NixOS root on zfs and etc. anyway, 5 more clouds to go until release), I thought, could ChatGPT ever be productive enough in maintaining infrastructure? Not that I haven't heard of it, I'm user of ChatGPT it as everyone else, but when I had actual problems in infra, I even tried giving it as much context as I could and it was next to useless.

In linux when running virtual machines, by default iptable rules apply to the vm guests, which should be disabled if you want your sanity. I've been debugging this for a day, and asked ChatGPT to guide me, with logs all server topolgy and contexts. For crying out loud, I've even pasted in the culprit - the ipables rules which were blocking the traffic and it didn't suggest me that iptable rules were at fault.

When I think about it, programming is extremely precise. Having never used FRRouting before to implement routing for Eden platform it was quite a pain to get networking working across clouds. For google faggity cloud I've spent a lot of time debugging why in the world L2 frame doesn't travel between the hosts only to find out google implements its own faggity andromeda abomination network which doesn't even support L2 traffic. Meaning, in google cloud you have to rely on their slow router garbage which can never be adjusted realtime in terraform and they suggest your to run your own bgp node to interact with their faggity router! All because they don't do L2 traffic. I cannot spend bunch of time dealing with faggotry of google cloud so I simply enapsulated traffic between eden platform datacenters (which could be any datacenter implementation) in IP GRE protocol so it would fly as L3 traffic.

I will not treat any cloud specially and use their special faggotry nonsense just to make nodes across clouds talk when I have public ips in every cloud, so I should be able to implement my own routing, no? Google cloud faggots...

So, anyway, when doing this complex networking, usually, a single configuration misfire and traffic is gone. There's no leeway for error. I even had to redo networking, abstract it to have attributes for datacenters and I had to write configuration simulation in tests so now that I have got to a working state I could freeze the configuration to know for a fact I didn't break anything.

Maybe I just like the pain, but I can't wait until the day emerges where all of the issues I've been dealing with simply become compile time errors in high level Eden platform data and I don't have to deal with such low level details and can focus on finally shipping suite of applications I want to build on top of Eden platform.

ChatGPT, even given all of the context, if it makes mistakes in single place things don't work. And every time I used it to generate even skeleton terraform configs I always have to run it and debug. There was not a single time where I pasted code from ChatGPT and it would just work, except for simple queries like write lua function that sums 1 to 10. Apart from these toy examples AI is next to useless.

So the only use for AI seems to be when you need to write a polite email, generate a picture, rewrite some sentences - anywhere where precision is not important. In software engineering precision is crucial.

Let me ask you one thing, would anyone use a library that does a memory leak one in a million times? No, it would be dismissed as garbage. You have to rigorously test it to make it usable in real world in production.

Some indian faggot said with a smug face "there are no programmers in 5 years". Sure, I guess there will appear a batch of people blindly copy pasting things from ChatGPT and they'll eventually still need a programmer to fix/debug the mess which they have made.

AI coding monkeys think from a very narrow short perspective. For some reason, AI fags cannot imagine producing programs any other way than there are gazillion repositories with different programming languages and you MUST parse and process all of that context before you can contribute. Someone is doing JavaScript with NodeJS? Parse and analyze that faggotry! Someone is doing Ruby, their app is full of bugs? Parse and analyze this faggotry too!

What I do with Eden platform is radically different. I'm looking down like I mentioned in another post. My data is defined in tables and columns. All columns are sequential in column store provided by EdenDB so analyzing data is blazing fast and can be parallelized to all cores. All applications are in Rust (I'll add OCaml if there is ever NATS support added, or I might expose Rust C library for OCaml to talk with NATS). So, in Eden platform you just add high level data, it is all compiled and analyzed and every application interacts correctly from day one. There is no longer need for NodeJS faggots or ChatGPT. To tell you whats wrong or to write many tedious tests. Currently, when writing app in Eden platform literally 900 lines of Rust get generated and I write 100 remaining which interact in typesafe manner with the rest of the ecosystem, making me literally 10x developer. I don't fear to interact with database/queues or other apps even without tests.

That is much more useful than some garbage generated by ChatGPT which may or may not work (usually didn't work for me). I want things to work the first time, with compile time errors knowing everything will work. I'm not interested in some probabilistic vomit I need to debug again and again and again.

Even if I'd let ChatGPT to write documentation I need to proof read it again anyway, but hey, at least it sticks to word vomit now!

Now, I still believe Eden platform will drastically reduce engineering power needed, but it will not be by producing random vomit that doesn't work - it will be code generation and compile time errors before shipping to production. That will be the big firing of Ruby and JavaScript monkeys, not ChatGPT.

Have a good day bois!
#3
Development Tips / Feature velocity
November 28, 2023, 07:21:40 AM
Today I want to talk about pain that a lot of engineers cause to themselves.

I will tell you right now - no company at a high level gives a tinyest crap about implementation details of any component you create. Someone might say I'm saying that the sky is blue. Apparently not, because the world is infested with yaml abominations and NodeJS.

Let's pick example, there are two NodeJS services. There's a mismatch in how one service calls another and its an error. It turns into a Jira ticket.

Project manager asks what's wrong with that? Engineer says "well, one NodeJS service doesn't know schema of other service, we need to run tests". Poor project manager has to nod head and say "ok ok".

This is bullshit excuse. Your system, oh fellow engineer, who you came up with of hundreds of NodeJS microservices is an abomination and you should feel bad. You're an idiot and it is your fault. When you think about it, if both services were in same executable, in Rust, it would be just compile time error and you'd have to fix it to ship. When services are separated, the exact same error for some reason becomes okay now!

Anytime such excuse comes to light "we can't verify kubernetes deployment yaml hence it errors out know because our helm chart repo is abominable pile of yamls that doesn't work together" its the fault of idiot engineers.

Anything that gets in the way of the high level goals of adding features to make your customers happy is the fault of the engineers. You picked Ruby on Rails garbage and now suffer many production runtime errors because of that? Its your fault. Your system is a repository of crappy incoherent yamls that have no typesafe enforcement so you resort to test environments to catch such errors? It is your fault. You can't deploy new database in 5 minutes with HA, replication and backups and it doesn't interact with your app in a typesafe manner? It is your fault.

Pagan monkeys have this funny idea that every system should be open and you should be allowed to put anything in it, like dynamic type schema registration, dynamic execution hooks or whatever. "Great software is not built, it is grown!". Imbeciles. They're saying that because their mom was an open system, open to 100 different guys that is, and look at them now.

What I do with Eden platform is radically different. There are no incoherent yamls, there's a single source of truth database which can be defined in eden data language or lua (probably also with webassembly in the future if there's need). I already implemented AWS terraform code generation, which uses AWS transit gateway if you have more than one datacenter in AWS, but uses wireguard to connect to all other clouds. I'll implement 6 more clouds for the initial version and they'll all talk together via wireguard VPN with high availability and OSPF routing since day one (you can't deploy half-assed no production ready configurations in Eden platform).

You see, since I said from the very beginning, if something doesn't work in production in Eden platform its my fault as an engineer. It is much more difficult to catch all errors during compile time than just leave users swearing and sweating in production due to runtime errors caused by incorrect configurations. Now I have no excuse like today's yaml fags. So I can actually solve these problems by analyzing data in eden platform compiler which tells me within second if my data is wrong. It tells me instantly with compile time error, that I deployed all DB instances only in single datacenter, which should be scattered around datacenters in region to tolerate DC loss. It tells me instantly if query application is using is no longer correct because schema changed. It tells me instantly if one frontend app link no longer can reach other frontend app page during compilation.

So all of these just become compile time errors. So guess what happens with feature velocity? Since all of the previous excuses become compile time errors there's no reason why you couldn't implement REST call to another service in 5 minutes - compiler tells you instantly schema is changed or is incorrect because we took responsibility. Compiler will tell us instantly if prometheus alert is using non existing series. Compiler tells us instantly that we forgot to configure virtual router IP in certain datacenters and clouds where it is needed.

What an old experienced SRE had to do himself by knowing of the system now compiler tells us to do simply it has all the information together.

So what should you do for the rest of the time once you're using Eden platform (hope to release initial version next year finally)? You just develop features and everything works together from day one. And you can do work of 100 engineers alone now. I'm very excited to release this project next year as no one ever done this and it will radically change the way things are done now. Most yaml masturbating excuse engineers - you're likely to get fired soon.

Have a good day bois!
#4
Development Tips / Looking down
August 30, 2023, 05:53:50 PM
For my thoughts are not your thoughts, neither are your ways my ways, saith the LORD. For as the heavens are higher than the earth, so are my ways higher than your ways, and my thoughts than your thoughts. - Isaiah 55:8-9
And he said unto them, Ye are from beneath; I am from above: ye are of this world; I am not of this world. - John 8:23
I am Alpha and Omega, the beginning and the ending, saith the Lord, which is, and which was, and which is to come, the Almighty. - Revelation 1:8

Let's talk about two directions software is developed in this world. Say, you develop an open source library. You're in for the world of hurt. How many different people in different contexts would try to use your library? Some idiot in golang book (yes, I've read a golang book just to hear them out, that reassured me even more that golang is trash and one day I might write dedicated post roasting golang) claims that if you want to make useful software it has to be generic. There is that evil word again.

The truth of the matter is if you make stuff generic your things are inherently limited. You are looking up. Looking up means like looking up to the sky, whether it will rain or not, you don't control that. The people that use your library are the ones from the higher context, in a specific organization looking down into your library whether it is usable in this context or not. Long story short, users of your library have all context to use it so they have much easier time to decide what to do. They don't have to use your library, for specific case they could develop their own custom component.

As soon as you put yourself into context of what you want to achieve you start looking down. You have full control of your project. Well, I guess someone could say that as I'm developing Eden platform (I'm roughly 60% there I think, developing infrastructure tool that has cloud/provisioning/versioning/logging/monitoring/ci/cd/security/applications/load balancing/databases/queues and etc. integrated together is quite a lot of work, believe me) I am imagining all the context.

In Eden platform everything is assumed, private ip scheme is assumed. Routing amongst subnets is assumed. I assume datacenters will have certain ip prefixes, like 10.17.0.0/16 for one datacenter and 10.18.0.0/16 for another datacenter. Hence the routing is simple. I assume datacenter can have up to 65k hosts, all inside /24 subnets inside datacenter like 10.17.1.0/24 for one subnet and 10.17.2.0/24 for another. I assume every datacenter has at least two wireguard gateways to connect to all other datacenters which is checked at compile time and you must fix it to ship. I use OSPF in FRRouting to route across subnets and regions and I don't need anything else.

So, developing Eden platform forced me to think in global ways of how one organization can develop everything as a single unbeatable monolith which supports infrastructure of around eight million hosts. I am thinking globally. And that required some refactorings on my part early, to figure out how regions, datacenters and interconnections between datacenters play together for all infrastructure. I was forced to go through those decisions early, not when you need to expand to multiple datacenters in production and nobody has clue on how to do that and then it takes years because of poor early decisions.

The inferior alternative to looking down is to look up, be someone's bitch. For instance, I could have used something like dnscontrol for DNS and pray they support such and such provider for all dns records. Well, that's not good enough if you want to make all assumptions and have all control. So guess what Eden platform does? That's right, we run our own DNS servers, we use rock solid BIND that stood a test of time, hence we can look down. We do our own routing. We do our own builds and rollouts with rock solid and reproducible Nix build system.

I'm not yet into this at the time, but plan is also to just generate all the terraform code needed for every datacenter. Say, you'll specify in datacenter `implementation` column that aws is the implementation and then Eden platform will generate all the terraform for all the machines in their appropriate subnets which obey Eden platform ip scheme and they'll be automatically connected via wireguard to the rest of datacenters of Eden platform, which might be on premise, google cloud azure and etc. And if more than one AWS datacenter exists they'll be connected with native AWS transit gateway instead of wireguard. We can do tricks like that just because we have all the information about our intrastructure, and don't have to limit ourselves with wireguard across datacenters.

It's a lot more work, than say, some absolutely worthless project that I don't understand why anyone would use - FlywayDB. Typical Java crap that... Executes schema migrations. And a lot of people were convinced to use this nonsense. Eden platform rolls its own schema migrations because it's very simple to do BEGIN; execute all migrations; COMMIT ourselves. Database already provides these abstractions that make it easy. However, if key value store was used it would be much more complex.

So, I do not want to release half assed trash like FlywayDB which does one thing and you need to integrate it to everything else. For Eden platform to be useful it must connect and make everything to work together from day one. Eden platform should be all that you'll need, where everything is integrated and working together since day 1, just like Apple strives to do. I want to make assumptions about all the inrastructure, hence we must take control of all the components. When we take control of all the components we are looking down and our job becomes easier, while if we were looking up, such project as Eden platform would be practically impossible.

Man is taller than a woman and looks down on a woman. Say many men use the woman, like the library we talked about. How do you call such a woman that many men looked down upon and used her? We call her a harlot, and rightfully so.

In a perfect design for which we strive, if you look up you can only look up into one direction, have only one master to whom the component will fully submit and not be influenced by any other component. No woman can ever be shared between two men, it is an abomination.

Of course, Eden platform uses third party components that are generic, used up, and because they are not aware of the certain context, suboptimal in certain places. This is just the beginning to get things up and running.

Once Eden platform is built and running in production, then we can allow ourselves to have custom, better optimized components in certain context where generic ones are limiting. But that is very far into the future.

Long story short, if you want to make your life easy, do not be like an open source fag that desperately tries to support every new itch of platform under the sun. For instance, I'll likely release Eden platform only under NixOS because I consider other operating systems a waste of time. To make your life easy, start looking down, globally, about the global context of your app so you can make assumptions and you'll avoid so much trouble down the line where most other engineers will be bogged down by meaningless indecision inducing details.

Have a good day bois.
#5
The pattern V2 / Eden DB Improvements 2
June 07, 2023, 01:16:27 PM
Sup guys, it's been a while you lurkers that read my posts but stay silent.

I'm working on Eden platform now, and basis of that is EdenDB, to which I make changes as I need them when working on eden platform. I've made quite a few improvements since last improvements post.

Ability to refer to other element's children through REF FOREIGN CHILD syntax

The need for this arose when I needed for abstractions, like NATS or PostgreSQL instances to specify on that volumes they reside.

Say this is a server table (simplified)
TABLE server {
  hostname TEXT PRIMARY KEY,
}

It has volumes as children (simplified)

TABLE server_volume {
  volume_name TEXT PRIMARY KEY CHILD OF server,
  mountpoint TEXT,
}


So say you have server-a with defined volumes

DATA server(hostname) {
  server-a WITH server_volume {
    pgtest1, '/srv/volumes/pgtest1';
  };
  server-b WITH server_volume {
    pgtest1, '/srv/volumes/pgtest1';
  };
}


And we need to define a postgres instance of a single cluster (simplified from real schema)

TABLE db_deployment {
    deployment_name TEXT PRIMARY KEY,
}

TABLE db_deployment_instance {
    deployment_id INT PRIMARY KEY CHILD OF db_deployment,
    db_server REF FOREIGN CHILD server_volume,

    CHECK { deployment_id > 0 },
}


So now we say that we want our foo logical database, with three replicas defined, one will be master with patroni and other replica.

DATA STRUCT db_deployment [
  {
    deployment_name: foo WITH db_deployment_instance [
      {
        deployment_id: 1,
        db_server: server-a=>pgtest1,
      },
      {
        deployment_id: 2,
        db_server: server-b=>pgtest1,
      },
    ]
  }
]


Notice, how we refer to the volume of `server-a` and `server-b` where we want data to reside using `=>` operator, which means child element.
We could nest this arbitrarily deep.

So, by using foreign child syntax syntax we do two things:
1. Specify which server runs the database (parent of the volume)
2. Specify where data on server runs

And, of course, you cannot define non existing elements in EdenDB, so you cannot make a typo of specifying non existing server or volume (unlike in typical yaml hell)

Full gist is here https://gist.github.com/cultleader777/41210e58026a0bec29f7e014945e40b0

Refer to the child element with REF CHILD syntax

Another issue I had working on eden platform is that I wanted to refer to the child element from parent element.
Say, server has multiple network interfaces, how to we specify which interface exposes ssh for us to connect and provision server with?

Say this schema (simplified from original)

TABLE server {
  hostname TEXT PRIMARY KEY,
  ssh_interface REF CHILD network_interface,
}

TABLE network {
    network_name TEXT PRIMARY KEY,
    cidr TEXT,
}

TABLE network_interface {
    if_name TEXT PRIMARY KEY CHILD OF server,
    if_network REF network,
    if_ip TEXT,
    if_subnet_mask_cidr INT,
}


So, network interface is a child of server and we can refer to the child from the parent so that we know on which network interface we ssh to every machine.

DATA STRUCT network [
  {
    network_name: lan,
    cidr: '10.16.0.0/12',
  }
]

DATA server(hostname, ssh_interface) {
  server-a, eth0 WITH network_interface {
    eth0, lan, 10.17.0.10, 24;
  };
}


Also, we can refer to child of arbitrary depth with the `=>` syntax from parent.

TABLE existant_parent {
    some_key TEXT PRIMARY KEY,
    spec_child REF CHILD existant_child_2,
}

TABLE existant_child {
    some_child_key TEXT PRIMARY KEY CHILD OF existant_parent,
}

TABLE existant_child_2 {
    some_child_key_2 TEXT PRIMARY KEY CHILD OF existant_child,
}

DATA existant_parent {
    outer_val, inner_val=>henloz WITH existant_child {
        inner_val WITH existant_child_2 {
            henlo
        }
    }
}


As usual, EdenDB fails to compile if existing child elements don't exist.

Full example here https://gist.github.com/cultleader777/d4f26449d2814a30d6b34e55c5d19c76

Detached defaults with DETACHED DEFAULT syntax

I had an issue of working on Eden platform that if default is defined in the database schema then it can't be changed by the user.
This is because eden platform schema resides in one set of files and user defines data in his own set of files.

Say, server has hostname and belongs to tld in the schema file

TABLE server {
  hostname TEXT PRIMARY KEY,
  tld REF tld DETACHED DEFAULT,
  fqdn TEXT GENERATED AS { hostname .. "." .. tld },
}

TABLE tld {
  domain TEXT PRIMARY KEY,
}


Now, it would be not nice to specify to which TLD server belongs in the default. Every user of eden platform will have its own domain.
So tld element is DETACHED DEFAULT. It must be defined by the user, and can only ever be defined once. If it is not defined, or defined multiple times it is compiler error.


DEFAULTS {
  // defines default for table 'server' and column 'tld'.
  // you cannot define defaults for non existing tables
  // and column must be marked as detached default
  server.tld epl-infra.net,
}

// now we can define data with detached default
DATA STRUCT server {
  hostname: server-a
}

DATA tld {
  epl-infra.net;
}


Full example here https://gist.github.com/cultleader777/3823ccef5c22b4b086c2468ab9e2e89c

And these are the main features I needed to add to EdenDB so far while working on eden platform compiler.

See you later bois!
#6
Development Tips / Testing assembly much?
March 12, 2023, 06:13:34 PM
This is a long overdue post about assembly. Typically, what we know about assembly language today is that those are low level instructions that fiddle very low level operations with CPU registers, memory, interrupts and etc. In this day and age nobody but compiler writers care about assembly. But even then, if you write a compiler LLVM is available to you where you emit LLVM IR (intermediate representation) instructions and LLVM generates assembly code. It could be x86, arm, PowerPC or any number of supported architectures.

Whatever new assembly language comes out specific for certain chip only very few people of programmer population needs to understand that to port it to yet another platform and all that will be available for the rest of the programmers to use. Today, 99%+ developers don't care about assembly. It is good to understand what it is and how it works, to have conceptual understanding, but to actually fiddle assembly code by hand you either need to have extremely good reason or you're just pretentious or insane.

Why am I talking about this? As I'm developing Eden platform now I need to generate a lot of code. Be it Rust code, shell scripts, nomad job files - all of them are generated now. I don't write these by hand. Most people what is generated in my framework today need to write by hand, care about it, maintain it, fiddle with it, have tests for it.

What I see as inevitable future most of the code people write today will turn into assembly automatically generated without mistakes. No more need to maintain those, you just connect high level table data in eden data language and things will just work. You will not be able to misconfigure service with a bad dns name to connect a certain postgres instance like you can in a garbage yaml hell. You will not be able to operate in DNS names - DNS names to consul services will simply be an irrelevant implementation detail. Part of our generated assembly. What you want to say instead is that deployment of this service speaks to this instance of database which has this and this schema. You don't care about implementation details of DNS.

Today virtually everyone tests this higher level assembly. Is service running? Does it open a port? Does it respond to such and such http request with such and such response?

Of course, compiler writers also have huge test suites that test assembly, certain behaviours of generated code. In the beginning of GCC compiler there were probably lots of bugs, with time they became less and less common to a point where average user encountering a compiler bug is similar to a chance of winning a lottery. Usually, once GCC or rustc runs and compiler successfully emits output, you assume that basic behaviours are correct.

But how can that be? Rustc emit executables with assembly code! You would be crazy to rely on assembly? Since there are high level rules in Rust which are enforced with tests and we now mainly trust that compiler is reasonably correct we trust Rust programs much more than Javascript programs (if you have any sanity) even though both programs are running on the same CPU and they're running same assembly instructions underneath.

With the pattern, most yamls, infrastructure configurations that you'd need to maintain by hand become assembly. Most Rust application code not written by the user becomes assembly. Consul configs become assembly. Nomad configs become assembly. Vault configs become assembly. Postgres configs become assembly. SQL migrations become assembly. NATS configs become assembly. MinIO configs become assembly. Consul policies become assembly. Vault policies become assembly. Nomad job declarations become assembly. Server nix configurations become assembly. Application build scripts become assembly. Nginx configs become assembly.

Another property of assembly is that compiler optimizations change and assembly changes but code doesn't have to. Users don't care. Now at this point for instance I use Nix to provision all servers and have reproducible builds. It is my favorite OS and package manager which will make Eden platform rock solid. But hypothetically, what happens if one day for some reason I will no longer like NixOS as server operating system? I'll just change the assembly code generated for server provisioning and VM images built (user doesn't care and doesn't need to know) to something else in one commit and that's it. Assembly will never be the most important. Assembly is swappable. Assembly is an implementation detail.

And what is the future of assembly? It will become irrelevant. Needless to say there are lots of errors in Eden platform compiler I'm working on during development, but the more and more test written, the more mature this project will become it will be like GCC and Rustc - once compiler runs, tests assumptions/consistencies/port clashes/RAM boundaries/typesafety of applications/db query correctness of your entire infrastructure of 1000 servers and 1000 applications and emits source outputs in a few seconds for your entire infrastructure - you'll just assume things will work and deploy with a smile. Without spinning up thousands of machines for testing. Without spinning up thousands of services.

And what is the future of developers that today need to maintain such assembly? Check job postings for x86 assembly programmers and find out ;)

Have a good day bois!
#7
And the angel which I saw stand upon the sea and upon the earth lifted up his hand to heaven, And sware by him that liveth for ever and ever, who created heaven, and the things that therein are, and the earth, and the things that therein are, and the sea, and the things which are therein, that there should be time no longer: - Revelation 10:5-6

I'm at the point where I'm developing eden platform, which will be the first open source version of the pattern. I'll likely be able to release the early achy breaky version as a proof of concept in half a year.

I came across an interesting thing when developing this project. Now my infrastructure and apps are all data. And I picked nomad to be the scheduler, vault storage for secrets (I run full hashicorp stack and I think kubernetes is cancer). Same thing that happened with Java and C# happened with Kubernetes and Nomad. Java is a complete and utter garbage of a language, C# had the hindsight of all the mistakes Java made and used it to create paid but much more superior product. Kubernetes also is the first Java, yaml hell and Hashicorp used its bad practices to create much better and pleasant orchestrator to work with.

When I was developing the pattern of my infrastructure I had a very specific problem I needed to solve.

Nomad application needs to access a secret that depends on database existing. If you run infrastructure the first time, neither database nor application exists. We're still in the planning stage.

So, it would be very complex if first we deploy database, then generate passwords and only then put password to vault and application can access it. Nasty chain of dependencies.

Instead what I did, logical plan of all the applications is built in memory. Application states that it will want to connect to the database X. Then code is generated that secret simply exists there in the nomad .hcl job file. Then also code is generated to provision that secret, generate random 42 character string and put it in vault. Code is also generated to provision that database user to access it.

What typically happens in companies, you need access to the database. All things happen in chronological order:
1. Database is provisioned
2. User credentials are generated
3. Credentials are provided to the user
4. He uses the database

What, I did instead, everything is happening at once. Before even application is deployed it knows it will need so and so secret to access it. Before database is deployed it knows it will need so and so user for application which doesn't even exist yet. This way, with the pattern, I see everything at once. I see all the applications before they even exist. I see all the databases before they are even provisioned, and they perfectly work together the first time.

This is a true godlike power, knowing and having all information at once in one place in this small infrastructure world I am creating.

Now all these times where God predicted something will happen in the bible, why God has infinite power or how God can nudge anything to happen in his direction make perfect sense. God sees everything at once, there is no before and after in the eyes of the LORD.

But, beloved, be not ignorant of this one thing, that one day is with the Lord as a thousand years, and a thousand years as one day. - 2 Peter 3:8

LORD has the higher ways we cannot understand:
For my thoughts are not your thoughts, neither are your ways my ways, saith the LORD. For as the heavens are higher than the earth, so are my ways higher than your ways, and my thoughts than your thoughts. - Isaiah 55:8-9

God sees everything from above we can't see:
And he said unto them, Ye are from beneath; I am from above: ye are of this world; I am not of this world. - John 8:23

We, as flesh, think only of one dimensional world. What we see locally is what we react to, can see and touch. What we perceive as time is simply our restricted vision which is disconnected from the entire view of the universe that God has. One day I will also see as God sees, know as I am known of God.

For now we see through a glass, darkly; but then face to face: now I know in part; but then shall I know even as also I am known. - 1 Corinthians 13:12

So, like I mentioned, the pattern framework that I'm building will be the first of its kind. And as I mentioned, any design worth anything at all will have to inevitably resemble divine patterns found in heaven. This framework will have unlimited power within its own respective universe.

- We will know what ports are used for what service before infrastructure is even deployed. Port conflicts will be impossible, and we won't need to spin up machines to test this.
- We will know that too many services are scheduled on one node with memory requirements that go above bounds of machine.
- We will know that 100 applications will perfectly interact with binary queues with perfect typesafety before anything is ever deployed.
- We will know that queries of every application work and hit indexes before anything is deployed.

No more spinning up cluster of machines to see if things work together, all of that will become automatically generated assembly perfectly interacting with each other.

I'm very excited about the future of eden platform, and can't wait to release this project to the world. There is nothing like this.

Happy new year by the way!
#8
Development Tips / The infinite whac-a-mole
October 01, 2022, 11:24:46 AM
Today, there are two ways to develop software under the heaven. Namely:
- A game of infinite whac-a-mole (virtually all of the software development today)
- Quadractic improvements (the pattern)

To understand today's game of infinite whac-a-mole let's create a matrix, rows are applications and columns are features


| application | monitoring | database access | queues | logging | proxying | load balancing | .. | feature 1000th |
|-------------+------------+-----------------+--------+---------+----------+----------------+----+----------------|
| app 1       |            |                 |        |         |          |                |    |                |
| app 2       |            |                 |        |         |          |                |    |                |
| app 3       |            |                 |        |         |          |                |    |                |
| ...         |            |                 |        |         |          |                |    |                |
| app 1000th  |            |                 |        |         |          |                |    |                |


This matrix is of many applications in rows interacting with the same features. There can be very many features and very many apps. In our imaginary matrix we have 1000 features and we have a thousand apps.

Today what happens in big companies, developers are being hired to whack moles in this table for some apps or features. Developers are being thrown to at this table, for instance, to build load balancers for the apps, to build persistence for the apps, or just develop apps and talk with infra if you need some components done.

Basically, developers can cover only small parts of this table. Imagine, performance team is created and they need to expose metrics for a certain application to collect them. They need to go through specific apps and mark only one square of this table as completed. Same with many other features. Sometimes improvements are quadratic, for instance, in kubernetes cluster logging is built once and all apps logs go to one place. Or, for instance, NixOS is a quadratic improvement because it gives reproducible builds if all the apps use it. But anyway, whenever your task is "go to such and such an app and fix this bug about such and such feature not working" - you're whacking one x on this infinite table. You're doing monkey's work putting out fires forever. For instance, some database query is not tested, returns null somewhere and system doesn't work and that's extra work. Or some golang garbage app leaks memory due to having very weak abstractions (don't forget to manually put your precious defer everywhere, faggots! I'll just use rust and don't do that at all and resources will be reclaimed automatically).

With the pattern we focus only on quadratic improvements. We do things once, and cover them for every app. We prevent entire class of bugs because we use only rust and ocaml. No nil pointer exceptions and no defer garbage like in golang. We cover database access for the entire column for every single app in the infrastructure - we know that queries that apps use are valid, backwards compatible and that hit indexes (no seq scans in production). We write once to check queries that apps use and we know all applications in our infrastructure will have the same property of only using valid queries that hit indexes. We write once prometheus exports as data for every app, then code is generated for that app to increment specific global variable about a metric and it will always work the first time for every app under the sun (if the prometheus variable is not used by the app that's a compiler warning as error and cannot end up in production). We have backwards compatible structs for every app and application can only use typesafe structures to access the queues and it will always work.

With the pattern, you typically do things once per feature column and all applications benefit. How many entries this matrix has, a million? Say it is million units of work. If one developer on average does 1000 units of work in a given year then you'd need 1000 developers to maintain all of this table. However, if you go quadratic, use the pattern, and you fill column for every application at once, that's only 1000 units of work and can be done by one developer in a reasonable amount of time. You see, when I said the pattern allows one person to do the work of 1000 developers I wasn't kidding. Square root of one million is one thousand, no? How much less work you'd have if you didn't have to test every application as thoroughly with integration tests and spinning up of machines? Knowing they interact with the rest of the system with perfect typesafety? Knowing your performance counters are automatically incremented when interacting with database or with queue? Counting every byte sent to queue or database? Knowing you automatically have monitoring of a thread for 100% of CPU usage of that thread? Knowing you have preplanned autoscaling policies in place ready?

That's why I don't consider big companies seriously. You'd think that people in google are supposed to be smart but golang is an utter half-assed trash. And that is easy to explain - they have thousands of developers to play infinite whac-a-mole. Tiny brain of an average googler never had to think about how to accomplish most work with the least hands. Most people who work there are a tiny cog in a wheel that do very specific small task and that are easily replaceable. Of course, just like in weight lifting, if you go into a work every day and only do ten sets with minimal weight your muscle won't grow. The only way to grow muscle is pushing it to the limit, doing few reps until failure with heavy weights you can barely lift.

The only way to reach infinite productivity is to be in a position where you're alone and you need to perform infinite amount of work. Like God is and God alone created everything:

Fear ye not, neither be afraid: have not I told thee from that time, and have declared it? ye are even my witnesses. Is there a God beside me? yea, there is no God; I know not any. - Isaiah 44:8

God of the bible doesn't know any gods beside him. Nobody helped him. Yet he alone had to create all the heaven and the earth and the sea and all that in them is. Leftist faggots, whenever they have their pathetic small work of being a kubernetes admin, they dismiss the ideas that replace them. Everything is relative! There's no panacea! Everything has pro's and con's! Yaml's are fine! Do more integration tests! We yaml maintaining monkeys are needed, pay us our salary! We need performance team! Ruby is fine, just write more tests and have more coverage! Many divided github repositories are fine, just do more integration tests! Hire more QA testers! When with the pattern when you go quadractic you can easily fire 90% of them and do things much faster.

Eventually 99% of developers will be easily replaceable and fireable, most work done today replaced with quadratic systems of the pattern. There will be only a need for a masculine plane developers that makes all things work together and understand how all things work through and through. Not some monkey who knows specific kubernetes yamls (which in the future will all be generated without mistake anyway with the pattern) and isn't capable of anything else. The developer that will be most useful in the future will be someone who is in God's image - knowing of how everything works in the system together. The rest will be people working in feminine plane who use the system in a typesafe way, filling in the blanks in the pattern system and hence will get much lower salaries due to much lower understanding requirements to do their job. Like in customer support where the vast majority of employees are women.

Just like when God created this earth - a huge framework where out of the box there is food, water, oxygen, sun for heat and energy, fertile soil, useful animals already and etc. - we just needed to use them without necessarily knowing intricate details of how everything works together.

Have a good day, bois!
#9
The pattern V2 / Eden DB Improvements 1
August 15, 2022, 07:59:30 AM

Sup bois, some improvements were made to the EdenDB to allow it to be much more flexible than standard SQL.

Basically, I was experimenting of how to represent domain problems as data, and I had to start with the servers.


TABLE server {
  hostname TEXT PRIMARY KEY,
}


Then I wanted to solve the infinite problem - how to check that no server has duplicate ports.

But ports are used by many abstractions, say, docker containers, systemd services and so on.
How do we ensure that different abstractions that use ports do not take duplicate port on the same server?
I kinda fell little short.

Let's see how reserved port table looks.


TABLE reserved_port {
  number INT PRIMARY KEY CHILD OF server,
}


Port is child of server. Now, say, we have docker containers. How do we refer to the reserved ports?

Before improvements shown in this post this is invalid


TABLE docker_container {
  name TEXT PRIMARY KEY CHILD OF server,
}

TABLE docker_container_port {
  port_name TEXT PRIMARY KEY CHILD OF docker_container,
  reserved_port REF reserved_port,
}


We couldn't refer to a reserved port because there's no unique key.

But then I thought, wait a minute, if both elements are ancestors of server, why the uniqueness context for port must be global?

If you think about it, the uniqueness context for such table that is child of anything ought to be the common ancestor. And if we imagine that every tables common ancestor is imaginary root table, then it makes perfect sense - everything is unique in the root table context.

This is how current topology looks visualized:


So, basically, the concept of a foreign key would be much more useful, if REF to another table would refer to the uniqueness context of the parent of the referred table.

So, having many different abstractions we can reserve ports in the single server so they would never clash and we find out about this before production when some systemd service can't start!

Let's define some fictional docker container running on some server with reserved port:


DATA server {
  epyc-1
}

DATA STRUCT docker_container {
  hostname: epyc-1,
  name: postgres
  WITH docker_container_port {
    port_name: main_port,
    reserved_port: 5432
  }
}


This so far does not work because of an error that reserved port does not exist in server:

NonExistingForeignKey { table_with_foreign_key: "docker_container_port", foreign_key_column: "reserved_port", referred_table: "reserved_port", referred_table_column: "number", key_value: "5432" }


We must reserve the port also.

DATA reserved_port {
  epyc-1, 5432
}


Now stuff compiles. And we cannot add more `reserved_port` with same value or stuff fails, if we copy reserved_port statement once again, boom:

FoundDuplicateChildPrimaryKeySet { table_name: "reserved_port", columns: "(hostname, number)", duplicate_values: "(epyc-1, 5432)" }


However, there's an issue that we would need to repeat reserved_port statement along with defining docker containers. Which leads to another improvement done to EdenDB: add rows with lua.

Basically, instead of defining this data by hand, now we can run lua code and insert to any table we want:

INCLUDE LUA {
  data('reserved_port', { hostname = 'epyc-1', number = 5432 })
}


And, of course, you must refer existing table and you must only define existing columns or compiler yiels at you.

`data` internal edendb function implementation is so trivial that I'll simply post it here:

__do_not_refer_to_this_internal_value_in_your_code_dumbo__ = {}
function data(targetTable, newRow)
    local queue = __do_not_refer_to_this_internal_value_in_your_code_dumbo__

    if queue[targetTable] == nil then
        queue[targetTable] = {}
    end

    -- we simply accumulate values to insert in lua runtime and then process
    -- them in one go in rust
    table.insert(queue[targetTable], newRow)
end


We simply have a global queue of rows to be inserted from lua and we iterate this map and insert data defined in lua in one go.

So, now, to avoid repetition we can simply define lua function that defines a docker container by inserting into all appropriate places we want:

INCLUDE LUA {
  function docker_container(hostname, containerName, portName, portValue)
    data('docker_container', {
      hostname = hostname,
      name = containerName,
    })

    data('docker_container_port', {
      hostname = hostname,
      name = containerName,
      port_name = portName,
      reserved_port = portValue
    })

    data('reserved_port', {
      hostname = hostname,
      number = portValue,
    })
  end
}


Data order doesn't matter, all checks are processed only once all data has been inserted into tables.

And we just call this function once in lua of defining postgres container, while encapsulating complexity, and deleting previous data definitions for this docker container:

INCLUDE LUA {
  docker_container('epyc-1', 'postgres', 'main_port', 5432)
}


Of course, I wrote a terse funtion as an example, in production likely there will be named map arguments with many default parameters provided internally in the function to make this more practical.

To be more practical, we include lua files for library stuff (this feature already existed):

INCLUDE LUA "lib.lua"


Full working gist can be found here https://gist.github.com/cultleader777/175fb37cb2ce1c9cb317ce2d187a926b

So, these are the two recent improvements that gave eden data language quite more power:
1. allowing foreign keys to refer to other child rows in the entity
2. defining data from lua, you can script anything you possibly want

Good day bois.
#10
The pattern V2 / Eden Data Language: introduction
August 01, 2022, 05:35:15 PM
https://github.com/cultleader777/EdenDB

So, this is a brand new language that focuses on... Simply defining data. Like YAML, but not garbage, typesafe, no nulls or NaNs, with schemas and blazing fast to query. Compiles and emits outputs in milliseconds and relentlessly checks logical errors to disallow funny stuff in production.

Let's have a taste, shall we?

Say we have a table of servers

TABLE server {
  hostname TEXT PRIMARY KEY,
  ram_mb INT,
}


They can have disks, as children

TABLE disks {
  disk_id TEXT PRIMARY KEY CHILD OF server,
  size_bytes INT,
}


Looks similar to SQL, who needs another SQL dialect? Ok, let's see how we can define server with disks, in three ways:

DATA server {
  my-precious-epyc1, 4096;
  my-precious-epyc2, 8192;
}


As you can see, much less verbose and straight to the point as opposed to INSERT INTO ... statement.

There is no concept of insert statement because data is immutable.

Let's add some disks 1TB and 1.5TB disks that are children to server

DATA disks(hostname, disk_id, size_bytes) {
  my-precious-epyc1, root-disk, 1000000000000;
  my-precious-epyc2, root-disk, 1500000000000;
}


The column order (hostname, disk_id, size_bytes) is explicit here but as we've seen with server default tuple order is assumed if ommited.

This is rather verbose of adding separate rows for every server we want into separate place. Also, we redundantly repeat disk hostname.

Could we have everything in one place, so that it would look structured?

We can, with the WITH statement, let's define the same but in more concise way:

DATA server {
  my-precious-epyc1, 4096 WITH disks {
    root-disk, 1000000000000;
  },
  my-precious-epyc2, 8192 WITH disks {
    root-disk, 1500000000000;
  },
}


And here's the magic. We can define child or foreign key elements with WITH keyword and key of parent element will travel to children. There can be many levels of children and WITH statement can also be nested arbitrarily deep. There's a bunch of logic to check for errors, you can read test suite.

But long story short, this is not the garbage of `.yaml` where you can write anything we want, then you run tests and pray it will work. All fields are checked of being appropriate type, all fields must be defined, no null values are allowed and all the stuff like that is checked. Consider this typesafety as strong as defining struct in Rust or OCaml and knowing it will never have nulls or funny values.

Also, there's another variation of `WITH` so that our elements begin to look completely like traditional nested maps in programming languages, this statement is also equivalent:

DATA STRUCT server [
  {
    hostname: my-precious-epyc1, ram_mb: 4096 WITH disks {
        disk_id: root-disk,
        size_bytes: 1000000000000,
    },
  },
  {
    hostname: my-precious-epyc1, ram_mb: 4096 WITH disks [{
        disk_id: root-disk,
        size_bytes: 1500000000000,
    }]
  }
]


So, we represented the same data in three ways and all this will end up as columns for us to analyze.

Aight, what can we do, how about our data correctness?

We can write SQL (thanks embedded sqlite) to prove anything we want about our data with good ol' SQL.

Let's write a proof that we don't have smaller disks than 10GB.


PROOF "no disks exist less than 10 gigabytes" NONE EXIST OF disks {
  SELECT rowid
  FROM disks
  WHERE size_bytes < 10000000000
}


How do we prove we have nothing of certain kind? By searching for it and finding none. This is important, because if this proof in eden data language fails, it will return rowid of the offending rows which can be printed out to user so he could figure out where to fix his data.

Okay, SQL proof might be a little overkill on this, we have also column checks (thanks embedded lua).

Here's how we could have defined the disks table to have same thing checked with lua:

TABLE disks {
  disk_id TEXT PRIMARY KEY CHILD OF server,
  size_bytes INT,

  CHECK { size_bytes >= 10000000000 }
}


Also, lets have a lua computed column for size in megabytes of the disk:


TABLE disks {
  disk_id TEXT PRIMARY KEY CHILD OF server,
  size_bytes INT,
  size_mb INT GENERATED AS { size_bytes / 1000000 },

  CHECK { size_bytes >= 10000000000 }
}


Lua snippet must return an integer or compiler yells at you. No nulls are ever allowed to be returned by computed columns either.

But wait, there's more!

Datalog is the most elegant query language I've ever seen my life. But for datalog to be of any practical use at all, we cannot have any queries that refer to non existing facts or rules. I've found a decent datalog implementation for rust https://crates.io/crates/asdi , unfortunately, it does not support `NOT` statements or arithmetic operators of less, more and etc. So, I'll show two datalog proofs against our data, one that works today (even though it is meaningless) and one that would be practical and would work as soon as asdi starts supporting less than operator.


PROOF "no disks exist less than 10 gigabytes, doesn't work today" NONE EXIST OF disks DATALOG {
  OUTPUT(Offender) :- t_disks__size_mb(Size, Offender), Size < 10000.
}

PROOF "just check that no disks with name 'doofus' exists, works" NONE EXIST OF disks DATALOG {
  OUTPUT(Offender) :- t_disks__disk_id("doofus", Offender).
}


As you can see, our computed column size_mb is available in datalog to query.

But wait, there's more! EdenDB exports typesafe Rust or OCaml code to work with. Basically, once everything is verified we can generate typesafe code and analyze our data with a programming language if we really want to perform some super advanced analysis of our data.

Let's run this:

edendb example.edl --rust-output-directory .


On my computer this compilation literally took 6 milliseconds (thanks rust!). It should never appear in a profiler in a compilation process, unlike most compilers these days...

Let's see the rust source that got compiled!


// Test db content
const DB_BYTES: &[u8] = include_bytes!("edb_data.bin");
lazy_static!{
    pub static ref DB: Database = Database::deserialize(DB_BYTES).unwrap();
}

// Table row pointer types
#[derive(Copy, Clone, Debug, serde::Deserialize)]
pub struct TableRowPointerServer(usize);

#[derive(Copy, Clone, Debug, serde::Deserialize)]
pub struct TableRowPointerDisks(usize);


// Table struct types
#[derive(Debug)]
pub struct TableRowServer {
    pub hostname: ::std::string::String,
    pub ram_mb: i64,
    pub children_disks: Vec<TableRowPointerDisks>,
}

#[derive(Debug)]
pub struct TableRowDisks {
    pub disk_id: ::std::string::String,
    pub size_bytes: i64,
    pub size_mb: i64,
    pub parent: TableRowPointerServer,
}


// Table definitions
pub struct TableDefinitionServer {
    rows: Vec<TableRowServer>,
    c_hostname: Vec<::std::string::String>,
    c_ram_mb: Vec<i64>,
    c_children_disks: Vec<Vec<TableRowPointerDisks>>,
}

pub struct TableDefinitionDisks {
    rows: Vec<TableRowDisks>,
    c_disk_id: Vec<::std::string::String>,
    c_size_bytes: Vec<i64>,
    c_size_mb: Vec<i64>,
    c_parent: Vec<TableRowPointerServer>,
}


// Database definition
pub struct Database {
    server: TableDefinitionServer,
    disks: TableDefinitionDisks,
}

// Database implementation
impl Database {
    pub fn server(&self) -> &TableDefinitionServer {
        &self.server
    }

    pub fn disks(&self) -> &TableDefinitionDisks {
        &self.disks
    }

    pub fn deserialize(compressed: &[u8]) -> Result<Database, Box<dyn ::std::error::Error>> {
        // boring deserialization stuff
        ...
    }
}

// Table definition implementations
impl TableDefinitionServer {
    pub fn len(&self) -> usize {
        self.rows.len()
    }

    pub fn rows_iter(&self) -> impl ::std::iter::Iterator<Item = TableRowPointerServer> {
        (0..self.rows.len()).map(|idx| {
            TableRowPointerServer(idx)
        })
    }

    pub fn row(&self, ptr: TableRowPointerServer) -> &TableRowServer {
        &self.rows[ptr.0]
    }

    pub fn c_hostname(&self, ptr: TableRowPointerServer) -> &::std::string::String {
        &self.c_hostname[ptr.0]
    }

    pub fn c_ram_mb(&self, ptr: TableRowPointerServer) -> i64 {
        self.c_ram_mb[ptr.0]
    }

    pub fn c_children_disks(&self, ptr: TableRowPointerServer) -> &[TableRowPointerDisks] {
        &self.c_children_disks[ptr.0]
    }

}

impl TableDefinitionDisks {
    pub fn len(&self) -> usize {
        self.rows.len()
    }

    pub fn rows_iter(&self) -> impl ::std::iter::Iterator<Item = TableRowPointerDisks> {
        (0..self.rows.len()).map(|idx| {
            TableRowPointerDisks(idx)
        })
    }

    pub fn row(&self, ptr: TableRowPointerDisks) -> &TableRowDisks {
        &self.rows[ptr.0]
    }

    pub fn c_disk_id(&self, ptr: TableRowPointerDisks) -> &::std::string::String {
        &self.c_disk_id[ptr.0]
    }

    pub fn c_size_bytes(&self, ptr: TableRowPointerDisks) -> i64 {
        self.c_size_bytes[ptr.0]
    }

    pub fn c_size_mb(&self, ptr: TableRowPointerDisks) -> i64 {
        self.c_size_mb[ptr.0]
    }

    pub fn c_parent(&self, ptr: TableRowPointerDisks) -> TableRowPointerServer {
        self.c_parent[ptr.0]
    }

}


To get rows from table we can only get them through TableRowPointer special type for every single table. This type is basically wrapped usize and is a zero cost abstraction in rust. But, if you were to use raw usize you'd have a chance of passing TableRowPointerDisks to the server table, which is impossible here. TableRowPointer is just an index to arrays of our column or row stored data.

There are only two ways we can get TableRowPointer for every table:
1. We do a seq scan through entire table to get valid pointers
2. Pointers to other tables may exist as a column in a table. For instance, we can get generated .parent from disk row, or children_disks column generated for server table

Database is immutable and can never be mutated. User in rust can only ever get immutable references to columns. Meaning, you can run thousands of proofs in parallel against this data without ever worrying about locks/consistency and etc. Once your database is compiled it is a done deal and it will never change.

So we don't have nasty garbage in our api like, does this row exist? I better return an Option! No, if you ever have a TableRowPointer value it will ALWAYS point to a valid row in a one and only unique table. You can clone that pointer for free, store it in million other places and it will always point to the same column in the same table.

Of course, we should prefer using column api for performance, getting entire table row is added for convenience.

Deserialization assumes certain order in the include_bytes!() binary data and does not maintain data about tables already read/etc - we just assume that we wrote things in certain order in edendb and read them back in the same order. Also, binary data for rust is compressed with lz4 compression.

OCaml api is analogous and gives the same guarantees. Immutable data, separate types for table pointers for each table and so on.

Okay, let's do something practical with this, let's prove that no intel disks are never next to some cheap crucial disks to not ever humiliate them like that!

We'll change schema a little bit, let's add, what is effectively, a disk manufacturer enum:


TABLE disk_manufacturer {
  model TEXT PRIMARY KEY,
}

DATA EXCLUSIVE disk_manufacturer {
  intel;
  crucial;
}


DATA EXCLUSIVE says, that this data can be only defined once. Otherwise, we could keep filling up this enum with many statements in different places, this effectively makes this table an enum.

Also, let's add our disks to contain the make column with this data:


TABLE disks {
  disk_id TEXT PRIMARY KEY CHILD OF server,
  size_bytes INT,
  size_mb INT GENERATED AS { size_bytes / 1000000 },
  make REF disk_manufacturer,

  CHECK { size_bytes >= 10000000000 }
}


REF disk_manufacturer means this column has to refer by primary key to a single row in disk_manufacturer, you can never add invalid disk manufacturer value in the disk table or compiler yells.

Now our data is redefined with disk manufacturer:

DATA STRUCT server [
  {
    hostname: my-precious-epyc1, ram_mb: 4096 WITH disks {
        disk_id: root-disk,
        size_bytes: 1000000000000,
        make: intel,
    },
  },
  {
    hostname: my-precious-epyc2, ram_mb: 8192 WITH disks [{
        disk_id: root-disk,
        size_bytes: 1500000000000,
        make: intel,
    },{
        disk_id: data-disk,
        size_bytes: 1200000000000,
        make: crucial,
    }]
  }
]


So, how would the rust source look to prove that no intel disk is next to a cheap crucial disk? There ya go, full main.rs file:


#[macro_use]
extern crate lazy_static;

#[allow(dead_code)]
mod database;

fn main() {
    let db = &database::DB;
    db.disks().rows_iter().filter(|i| {
        // we only care about intel disks
        db.disk_manufacturer().c_model(db.disks().c_make(*i)) == "intel"
    }).for_each(|intel_disk| {
        let parent = db.disks().c_parent(intel_disk);
        let children_disks = db.server().c_children_disks(parent);

        for pair in children_disks.windows(2) {
            match (
                db.disk_manufacturer().c_model(db.disks().c_make(pair[0])).as_str(),
                db.disk_manufacturer().c_model(db.disks().c_make(pair[1])).as_str(),
            ) {
                ("intel", "crucial") | ("crucial", "intel") => {
                    panic!("Are you kidding me bro?")
                }
                _ => {}
            }
        }
    });
}


Do you miss endless matching of some/none options to check if some value by key exists in the table or endless unwraps? Me neither. We just get all the values directly because we know they will always be valid given we have table row pointers which can only ever be valid.

Full example project can be found here

So, basically, let's recap all the high level tools EdenDB gives to be successful working and building assumptions about your data:

1. SQL proofs
2. Lua checks/computed columns
3. Datalog (so far meh)
4. Analyze data directly in Rust or OCaml if all else fails

Basically, 4 ways to analyze the same data from four different languages and all data is statically typed and super fast/column based in the end.

Also, there are these features I didn't mention:
- include multiple files syntax
- include lua files
- unique constraints
- sqlite materialized views
- countless checks for correctness (check enum count in errors.rs file)

To see all features of EdenDB check out the tests, because I usually try to test every feature thoroughly.

And more will be added as I see fit.

What can I more say? Having such foundations, time to build the most productive open source web development platform of all time 😜
#11
The pattern V2 / The pattern V2 architecture
August 01, 2022, 05:06:31 PM
This posts assumes you have read the main thesis and are familiar with the concept of the pattern.

Sup, after doing the pattern for some time something inevitably happened that happens in every craftsmanship.

I happed to improve upon initial designs.

So, I want to list a few pain points I had working with the pattern v1:

1. Representing abstractions as data is kind of tedious, even in high level programming language like OCaml. You need to write functions, with default arguments and stuff. Ideally, I'd see only data when I'm working with data and not be burdened by programming language concepts.

2. Proving stuff about your data is possible, but not too convenient. For instance, it is trivial to write SQL queries against data, but if you need to iterate in loops against same data doing what SQL would do becomes tedious pretty quickly.

3. Adding data is annoying. I used to have one list in ocaml with all rest endpoints, but if you need more teams, or logical splitting across files then you need to write them by hand to be merged.

What is the solution?

I inevitably came to the conclusion that there needs to be a separate data language to what I want to do where abstractions can be represented simply and trivially.

Hereby, I introduce EdenDB with its own Eden Data Language (.edl file extension) (covered in the separate post).

So, the new architecture, instead of two layers has three layers:
1. Data platform, highest level of data defined with Eden Data Language
2. Codegen layer, to generate all typesafe abstractions from our high level data language
3. The final feminine plane layer, where the user just fills in the blanks programming against typesafe interfaces



The rest of the posts in this board will be about development and implementation of the version 2 of the pattern, it will become an open source project available to everyone.
#12
Development Tips / The winner takes it all
June 12, 2022, 11:03:08 AM
Sup bois. Let's talk about some principle which explains why democracy cannot work ever work and inevitably one platform will emerge which will be unbeatable compared to others and will get all the userbase in the entire world eventually.

Things among things cannot ever be equal as explained in the world of inequality thesis. Also, in assumptions thesis I've demonstrated that more information equals more assumptions and more assumptions equals simplicity.

From this logic flow comes inevitable conclusion that to create utter and perfect simplicity you have to have all the information. From this we reach conclusion that we must have all of our information in one place so we could use it in any way imaginable, to check any assumptions and design decisions we want in our data. This is how the pattern was born.

This is all theoretical, and makes perfect sense once you understand the pattern, but someone who hasn't tried the pattern might not see it clearly at the first. This is why I love using real world examples in my posts to connect these theoretical ideas to reality to make them easy to understand for average developer. Let's talk about systemd.

The curious case of systemd

So, in a nutshell, unix bois were using init scripts to start their background services. They look horrible, are hard to maintain and are based on shell scripts. Thankfully, I've never written init.d scripts and thanks to systemd I will never have to.

Then came some guy which said the obvious thing, which you could easily deduce independently if you know the pattern and that assumptions lead to simplicity: if we know dependencies between services we can make boot order faster than with generic sysvinit scripts which start stuff at who knows when. So, basically, systemd units define services declaratively, as data. This is still far from the power of the pattern, which encompasses all infrastructure and every service within it (similarly like Nixops does, but not dynamically typed and easier to maintain and understand).

There was a huge pushback against systemd from linux bois. And usually I couldn't care less about what linux monkeys think about anything. They cannot understand to this day why they still don't have a normally functioning desktop linux distribution that would be adopted in the mainstream and why year of linux desktop is still a dream in a soyfaggot's mind. The problem in linux monkey's mind is that they cannot conceieve value in all things working together. For them it is always "this and this small service must work independently, doesn't know anything about anything, and somehow magically integrate to the system and stuff should somehow randomly work".

Anybody who used any linux desktop for some time usually brick their system after upgrades, installing debian, yum or other packages and God forbid they try to do any funny stuff with drivers once they start working. A package is expected to be thrown in the environment it knows nothing about, it knows nothing how system is already optimized and what is done to it and it somehow needs to figure it all out how to install itself without corrupting the system, and there is no downgrade option. That's why I think in linux no distro besides NixOS, which has downgrades, latest software, reproducible builds, has any right to exist and waste everyone's time.

The monkey minds who think linux desktop is great, except when it stops working after a year or two (depending on how tech savvy you are and how much you demand from your system) made a huge pushback against systemd, which solved practical problem of spinning up services in a decent way and faster boot order with dependencies. From the standpoint of the pattern, systemd is a super tiny step towards defining everything as data, has practical benefits of practically improving everyone's life with efficiency and service management. Systemd is definitely an improvement, yet degenerate linux pagan monkeys abhorred it, without even knowing why. Like dogs without understanding that bark at any passing person.

What I want to say with this? Systemd is a super small subset of the pattern, gives a few improvements in a single system. Good that it was adopted. But the endgame is the pattern and having all of the single companies data, as services, apis, databases, typed queues defined as data.

What will happen when an open source system will emerge that will have all the abstractions software developers need defined as data in a single codebase? I only do pattern for myself and don't open source it, because I wouldn't want imbeciles filling out pull requests for 100 features, making it generic and horrible - it is now perfect for me.

But inevitably, a day will come, where there will be one open source distribution of the pattern (similarly to serverless framework, but typesafe and not javascript garbage) supporting one database, one queue management system, one monitoring framework, one logging solution, one scheduler and one underlying operating system distribution (likely NixOS and its declaration files would be used as low level assembly in the pattern solution).

The day this day comes, 90% of devops/sre yaml and spreadsheet masturbators will become useless, 99% of pre deployment logical errors (like we have to have three or five zookeepers for quorum, or this data structure upgrade is not backwards compatible) will be caught by analyzing the data in the pattern. What will happen to worthless dynamically typed languages like ruby and javascript which must have monkeys maintaining them?

Incremental thinking

I remember some talk about go, improving garbage collection latency or something like that. Some guy spake about a cycle: we make efficient hardware. Then software becomes slow. We improve software. Then hardware becomes slow. We improve hardware. And so on and so on. We don't have to be as stupid as them. All that we need to do, to make drastic improvements and to see the endgame clearly - let's have everything as data. If we have everything as data, we become a small tech god in our own limited universe and we have ultimate power with the pattern. We can restrict any service talking to anything, its cores, what interfaces it sees - simply at compile time. No need to dynamically check access - it is restricted in the language, hence more efficient. If we have all as data, 90%+ abstactions/devops/infrastructure tools no longer make sense. They are hugely complex, fighting lack of information, they do incremental improvements at best, yet they cannot holistically take all the information and use all that power to get the best possible experience.

Linux monkeys are so far behind apple, which optimized their entire m1 chip to WORK TOGETHER with their software and give the best experience that it is not even funny. MuH fReE sOfTwArE mAdE bY dIvIdEd iMbEcIlE mOnKeYs wHeRe mUh sLiDeS dOnT eVeN wOrK aT tHiS tImE.

Don't be a monkey, don't zone into the small part of the system, treat it as a low level irrelevant swappable assembly (I'll make separate post about this assembly), think holistically, of making everything work together and you'll be miles ahead of every "eVeRyThInG iS a fIlE, i hATe sYsTeMd" unix imbecile.
#13
Enter ye in at the strait gate: for wide is the gate, and broad is the way, that leadeth to destruction, and many there be which go in thereat: Because strait is the gate, and narrow is the way, which leadeth unto life, and few there be that find it. - Matthew 7:13-14

I, as usual, was arguing my ideas with some people. Recently I argued with a literal faggot (literal faggot).

The argument from my side is very simple and I'll repeat it 100th time - if you have your problems defined as data in one place you can analyze them any way you want and catch a lot of otherwise very hard to catch errors before production. You should always strive to represent your problems as data if you want to produce correct and working software from the get go.

And the arguments of the faggots always boil down to such things: we'll, some developer might not want to write SQL. Or, some developers prefer ruby. Or, data in database changes, statistics change or what not.

That is, they can always find some edge case, as if it is justification to throw out overall solidity of the system for one minute detail that ought to be brought down to our control eventually anyway.

Let me give you an example of what they do. For instance, Rust, as long as you write safe code you cannot have segfaults. Faggot can say "we'll, you write unsafe code and have a segfault in Rust, hence the idea of Rust is invalid!". You see what these people do? They would dismiss the entire idea of Rust because of edge case of writing unsafe code which ought to be avoided. They dismiss the idea of the pattern, which catches 90% of trivial errors before deploying something to production because of some edge case that can still sneak into 10%, which we didn't cover yet. But, given we know enough data about our domain, we could finish even that in the long run.

Let's entertain the analogy of a kings house. House of the king is clean, spotless, everyone is dressed in good clothes and everyone smells nice. Interior has very expensive furniture. Then comes some poor fellow from the street, with dirty clothes, dirty feet and smells like hell. What will the king do to such a man? To go in front of the king you need to look appropriately and follow the rules of the king's house.

The pattern, meta executable with our domain problems defined as data is the house of the king. We have certain rules. We enforce our contracts with typesafety so we wouldn't see these errors in production. We perform custom static assertions and analyses on our data. Hence why I use OCaml and Rust in our king's house. If we want to bring in the likes of Ruby in our house, this would be equivalent of bringing in the smelly, dirty bozo which takes a dump on our golden floor of our royal house. We cannot have that. How can we ensure that Ruby upholds our type signatures we set for database queries and queues if Ruby itself cannot enforce its own types? Ruby is a dirty bozo that doesn't even go into the shower to wash his clothes. Same with Python, Javascript. Why should we bring such languages into our royal house, and make our house smell like shit because dynamically typed languages cannot enforce the basic contracts, which we could generate, but which would never be enforced?

Hence, the argument - some developers are familiar with Ruby, hence we need to support it, is worthless. I could say, some bozo sleeping near the dumpster wants to drive a lamborghini. So what? The crowd of dynamically typed ruby/python/javascript faggots are not to be considered when making decisions, their votes mean nothing. If they wanted a vote in the system of the pattern, where all honourable participants of the system honour their contracts, they need to wash themselves (in javascript, for instance, they'd must use typescript), wash their clothes, humble themselves and ask admittance to the king's house.

Current software companies are like third world countries. No law, no order. Most developers are dirty, smelly bozo's. They schedule meetings about how to make two or more components work together, because typesystem is in the mind of the bozo developer and he has to remember if there will be errors (which problem you'd never have with the pattern, as compiler is thinking for you). Hence the development is slow and everyone is frustrated.

You see, it is very easy to defile yourself. A virgin girl can lose her virginity drunk to some school bad boy and become defiled for the rest of her life, whom no self respecting man will want to marry. Also, sluttery destroys morality of the nation as well (Do not prostitute thy daughter, to cause her to be a whore; lest the land fall to whoredom, and the land become full of wickedness. - Leviticus 19:29). It is very easy to spray graffiti on the wall of your house making it look like it was vandalized by irresponsible teenagers that didn't receive whooping when growing up. It is very easy to do things wrong and go out of the way and make everyone else around you to suffer. Like Jesus said, broad is the way of destruction, but narrow is the way that leadeth unto life and few will find it.

Hence, we must separate ourselves from the world and its insanity, same principle for the church and same for the software development.

Wherefore come out from among them, and be ye separate, saith the Lord, and touch not the unclean thing; and I will receive you. - 2 Corinthians 6:17

Love not the world, neither the things that are in the world. If any man love the world, the love of the Father is not in him. For all that is in the world, the lust of the flesh, and the lust of the eyes, and the pride of life, is not of the Father, but is of the world. And the world passeth away, and the lust thereof: but he that doeth the will of God abideth for ever. - 1 John 2:15-17

Here's the illustration of what I mean. There's the sea of wrong, and developer, if he wants to develop in the sea of wrong he uses services like swagger declarations of http requests and then writes them by hand in his service. He uses non typesafe rails database, writes tests, hopes it works. He uses random data format when interacting with queues - millions of places where trivial mistakes can be made.



Below, in the sea of wrong, we have our royal built house with the pattern. We have few abstractions, like typesafe interactions with postgres database, typesafe interactions with queues, typesafe calls to other REST API services. We label queries if they are mutating the database, or are readonly. We can have stress testing of certain postgres queries which will be generated since we have our queries as data. We automatically create prometheus variables for every single query we have. We store every single query ever executed against the database, with their arguments, in clickhouse table for analyzing. We have our typesafe, efficient, binary format logging system, where we could generate how those will be represented in the frontend.

In our house, there's one law, one order, one way to do things. We only allow typesafe languages in our house. We have fewer, but super solid abstractions that ALL HAVE TO WORK TOGETHER in the same ecosystem and we don't need to support hundreds of databases/queues and so on. We do not write yamls (unless generated from typesafe config). Our configurations are typesafe enums where, for instance, I don't specify a port of kafka service, I specify with enum which cluster of kafka service talks to and all ports must be defined for every cluster and are checked if they are valid, cannot clash on the same machine and so on.

To build the house of the king took time, but once it is built, you cannot imagine you were a dirty bozo once living in the street and digging dumpsters once.

Have a nice day bois.
#14
.. is by saying it is generic. And we'll cover a lot of examples that reveal these hidden inefficiencies to the naked eye.

Lets start with foundations, a CPU. x86 or ARM is a generic compute machine. Generic compute machines will never be as optimal for special tasks as dedicated ASICs. Bitcoin mining first happened on CPUs. Then, since GPU aligns more specifically with the problem of massive parallel computation people mined with GPU's. GPU's are, again a generic compute device rather made for rendering games, so the next step were creating ASIC's. Well, there's a bus stop I between GPU and ASIC I skipped called Field Programmable Gate Arrays (FPGA), but I don't know if anyone tried programming FPGA's to mine Bitcoin. Anyway, the moral of the story is that CPUs/GPUs are a generic devices that will always be beat by specialised hardware. I just spent a paragraph to say that the sky is blue, so what?

Think about a world before GPU's, FPGA's and ASIC's. It wasn't that obvious then was it? And rest assured, we will challenge a lot of de facto ideas that we will predict disintegrate in the future.

Memory allocators.

Today a lot of people spend time developing memory allocators. ME's are implementations of a generic interface of malloc and free. Think of all the possible questions you have to ask yourself when implementing malloc. Does user want a big chunk of memory or small? How often is memory freed? Does memory travel between threads? The implementors cannot have the slightest idea, because such information is not passed to the function, hence they have to make generic approximations. That is, allocators code is full of if's and else's draining precious CPU cycles trying to fight this lack of information with dynamic analysis. Dynamism is cancer too, like I mentioned in another post.

There are standard operating system allocators, then jemalloc, now mi-malloc seems to be competing for the title of the "fastest" allocator. In reality they're just better approximating to the needs of the current time real world software.

But, for instance, if a routine uses small objects we could implement a simpler small object allocator and beat the generic one. Same with big objects. Same with objects that don't need to ever be freed. Specialised allocators will always beat generic ones.

Today in Rust you pick one allocator for everything and tada... I predict that in future compilers will perform static analysis like a skilled programmer and will pick specialised allocators for routines instead of one generic allocator for everything like jemalloc, mi-malloc and so on.

So, we just murdered the today's untouchable holy cow of memory allocators and this truth will eventually become obvious in a few decades to everyone. What's next?

SQL databases. Let's pick on generic solution of query planning. What happens today is, there's dynamic table of metadata about the data in the DB. If someone makes a query the DB has to parse that statement, analyse validity with the metadata, optimise the query with table, stats and so on.

Accepting a string is a generic solution. We must spend time parsing, analysing, handling errors in our precious runtime.

How about we move information about DB tables and queries to the compile time? After all ruby monkeys write tests to be reasonably sure about DB interactions before deployment to production.

What if database tables wouldn't be binary blobs in some generic filesystem format but rather a programing language constructs?
What if your DB was a generated code of a single object where tables were hash map arrays and your planned queries are simply exposed methods that you call and have typesafe results?
What if by defining the queries you need beforehand you could eliminate all queries that don't hit indexes and never deploy that?
What if, after analysing queries for tables you would determine that multiple tables are never queried together and can be serviced by multiple cores without even needing any generic locking mechanisms?

I'd love to use such DB instead and I will probably implement one with the pattern...

Another sacred cow is dead. Let's pick on Haskell faggots!

Smug Haskell academic weenies say "everything must be pure". Guess what? Making everything pure is a generic solution. Haskell crap because of that has to copy gazillions of objects and be inefficient, this greatly complicates the development of software projects with this impractical puzzle language.

Think of Cardano, now soon to be dead shitcoin that didn't deliver anything of practical value since 2017, having four years plus of a headstart versus projects like Avalanche, Polkadot and Solana, which use practical languages like Go or Rust and already have huge ecosystems. Meanwhile ADA Haskell faggots are just beginning to optimise their 8 tps smart contract platform. Even if they do optimise and become sufficiently usable (but will never reach speeds of Rust of Polkadot and Solana) their competitors will already be huge and nobody will need yet another blockchain.

So much for imposing a generic solution of purity to your project and destroying your productivity and develoment efforts.

The more specific solution would be controlled side effects. You mark a function pure and it can only use pure functions. I imagine a programming language will emerge, or maybe provable ADA already does this, where you can query and prove the code, that it does modify variable, is pure and so on.

Third cow done. Let's get serious: Operating systems.

Think of linux and the crazy amount of generic stuff it supports. I can guarantee that there is a ton of performance left on the table because of generic linux interfaces.

For instance, Terry Davis (RIP, you genius hacker soul!) wrote temple OS which specialised in games and in his OS he could perform a million context switches versus thousands of linux. That was because he coded a specific solution and circumvented lots of wasteful abstractions that are simply not needed in his context.

So far linux seems to suffice most applications with adequate performance, but I predict more and more unikernels will appear that will function as faster databases, load balancers, search engines and so on and so on. And unikernels will also eliminate many of generic system attack vectors, such as unintended shell access.

We could go on forever and ever about things that are generic and now are costly because of that, but I don't have infinite time. Simply, if you see inefficiency, or encumberance, ask yourself, is it because, for instance, XML, JSON or YAML is generic? If something is, how could it be made specific? Maybe these could be specific, typesafe language constructs? ;)

And you'll see angles you have never considered before.

By the way, nature seems to be created with all hardware, no generic intel chips. Specific bones, eyes, nails to every animal kind. So that speaks volumes of the infinite wisdom of our Creator!

Have a nice day
#15
Development Tips / Responsibility
December 11, 2021, 11:45:47 AM
I want to talk today about the responsibility and competence spectrum permeating all of the nature below:



Okay, so, on the very left there is utter masculinity. Think from the God's perspective, absolute power, absolute wisdom. God knows everything about everything and doesn't need anyone, everything that someone gets from God is by his grace toward that someone. This is the pefect, most possibly masculine image of God.

On the utter right there is utter femininity. A beautiful, submissive woman that is led by a masculine husband from the very left of the spectrum. If we talked about God this would be submissive followers, but principles are the same. Designs on this earth are fractal and self similar to patterns in heaven. What is on earth is a smaller copies of what is in heaven.

On the middle of the spectrum, where, in ideal world, no one should be, are either masculine, self sufficient women (disgusting) or weakling, faggity, feminine men (disgusting). These examples occour in nature, for instance, certain spiders where small, weak, feminine man is worthless and is eaten by a female after sex. Needless to say, God potrays these examples of how things ought not to be done with man which is made in the image of God.

Why is that? Why such opposite extremes? Why much more is required from masculine spectrum, to lead and know, to have strength and take care of the feminine spectrum?

Like we talked about generic vs specific thesis, to make the simpliest possible solutions you have to have all assumptions. To have the most possible assumptions you have to have all the information. Only such entity, that has all the information and all assumptions can make perfectly simple design decisions and impose simplest possible interfaces for the feminine plane to use them.

That is what meta executable in the pattern achieves - it has all the high level information about the project. REST Endpoints, queries, periodic tasks, all databases, their indexes, frontend elements etc. etc. Once we have all this data in meta executable, what would otherwise be a complex flow of getting/approximating this dynamic data from something somehow (like querying a database of executed query logs to analyze if queries are hitting the indexes - we're way too late, we could already be writing post mortems by now) now becomes trivial to solve as we have all the data we need defined in the project compile time in the meta executable.

All the dynamic metrics analysis systems from our standpoint are just generic abominations, which will never do the perfect work as we spake in generic vs specific thesis. They're neither fully encompassing, masculine, godlike enough, so they could provide everyone with perfect solution without extra integration code (they could, if they were part of the masculine plane executable in the pattern), neither they are perfectly simple, where you could provide typesafe API for them as consumers of the feminine plane. They're neither here nor there, hence, cannot be in the perfectly simple and beautiful feminine plane (like a beautiful, feminine woman), neither can they belong to the perfectly rational and all knowing and encompassing, infinitely powerful masculine plane.

Consider logging systems of today, elastic search + kibana. For the application logging all that is given is text. Output a line, then parse, possibly using complex regex who knows what. These will end up as separate parsed fields in kibana. Then make a kibana dashboard for every new crap app that comes out interpreting those plaintext messages of anything. And the work is never ending and certainly not perfect. This is because today's leftist faggots software devs cannot think straight, they provide generic output from the application and generic way to analyze that data which brings in bunch of complex caveats because it is not a specific solution.

Let's think about this problem from our perfect godlike meta executable, what we could accomplish with it instead?

1. Let's define every log message by type for every app in the masculine plane
2. Let's generate CapnProto schemas for every log entry and log only very small binary data that is the essence of the log message, using very little bandwidth in Kafka.
3. No more text, only possibly description next to log entry in the meta executable. Or, in meta executable we could specify formatting message how to visualize it for humans.

   Say, log message is how many eggs for what price someone bought in a store:
 
  struct LogMessageOfBuyingEggsInAStore {
    user_id @0 :UInt32;
    number @1 :UInt32;
    price @2 :Float32;
  }


  And we could provide a template string in the meta executable, with log entry of how to format this minimal, non text data in some GUI output:
  "User {user_id} bought {number} eggs in a store for price {price}"

  We could check that all of that is logical and works in compile time, in the meta executable.

  We could check that template variables exist for this log message, that we don't use all message variables, and so on and so on.

4. We could generate frontend to perfectly display our log messages according to the message types, no need to parse text.
5. Messages logged with perfectly typesafe function from the interface user in the feminine plane:

api.log_buying_eggs_in_a_store(price: 1.23, quantity: 7)


6. We could even attach alerting if we wanted to the log entries, if some error is really bad, we'd get an alert.
7. Since messages are CapnProto we'd spend 0 CPU time parsing them when dumping all them to ClickHouse

See how much more powerful solutions we can come up with that no soy leftist faggot could ever think of just by giving more power to the masculine plane where it rightfully belongs? And simple, feminine plane would only get typesafe functions on their api to log these entries? And leftist faggots tend to have the idea that something is either efficient or elegant, here we get both, efficiency with CapnProto and elegance of defining very high level abstraction for log entries where we don't even need to write more code once we developed it and things just work by adding more log entry types!

Just like a beautiful feminine woman could feel weak, doesn't need to have much wisdom inside the arms of a masculine husband who takes care of her and the family.

Like I mentioned, today, most software developers stand in the middle. They know little a bit of masculine plane, technical details, yet they feign utter ignorance when matter comes to making all things work together. For them it is unforgivable sin that database schema, queries and transactions should live together in a single codebase where they could be perfectly analysed together! Such faggots spend decades in meetings, figuring out the most complex possible flows in a rails codebase, where queries need to be checked for correctness, but also all the logic of interacting with the database must live with rails too because muh precious ruby faggots say "it would be unproductive to develop if we don't know database schemas". As if productivity is possible in the long run when developing with dynamically typed programming language. And craziest abominations are conceived, ultimate job securities that are then implemented for multiple years with no end in sight because more and more dynamic problems keep popping up.

The alternative is the pattern, all database schemas live in meta executable, all queries and transactions live in meta executable, everything is checked before the production with possibly enabled parallelism for performance and only if everything is ok, only then typesafe user API's with implementations are generated and everyone lives happily ever after. But no, let's create unmaintainable, fragile, complex abominations instead.

Like I mentioned time and time again, paganism is a mental disorder. God mocks feminine men in nature, think of all the spiders where male is small and female is huge and eats spider after sex. Such men, such faggots, if they don't fulfill the natural responsibility of calling the shots and leading the family have no purpose as nature shows us and do deserve to get cheated on, do deserve a used up slut of a wife, do deserve to ignorantly raise not their own children conceived by a cheating wife, do deserve to be only used for their money and do deserve the divorce court. These faggots are trying to enjoy in front of their women what only feminine plane was intended to enjoy - being weak, being incompetent and women ruling over them. And woman, who tries to stick her nose into a masculine plane, being the bread earner, calling the shots, being semi-smart (just a little bit smarter than feminine woman in reality, but will never reach the levels of the greatest inventors) does deserve to get smashed and dashed, does deserve to get her heart broken by the chad train that runs through her day and night in her youth, does deserve faggity, worthless, unattractive, feminine husband at the end of her youth and does deserve bearing weak and unstable children, her daughters being raised as worthless sluts and her sons raised feminine faglet losers.

None of these two variants, feminine man or masculine woman will ever be a good solution. Most software developers today fall in the middle, in the abomination which shouldn't exist. Hence, innovations are slow. They are a little bit smarter than the general population, but from the standpoint of a masculine plane all of them are insignificant small turds who will never develop anything decent.

Just think of Nikola Tesla who invented our entire modern electrical grid. After Tesla electricity innovation has stopped, same things that were used back then when he invented them are used today. Tesla knew it all about electricity, he was the hardcore innovator and brought most of these advancements to us. No wonder his labs were raided by secret agencies. But think about what that means - today software developers are brainwashed with the idea that no, you can't be the single innovator, innovations come when lots of "smart" people put their stuff together out of pieces and everyone is supposedly needed to make breakthroughs. Reality is much less romantic, you get miles ahead of every imbecile, you become prodigy, and obvious, beautiful, simple, much more advanced solutions just keep coming to you because everyone around you is a braindead and brainwashed monkey damaged by a few years of academia.

When I was in a university, there came a subject about God object that knows everything and it was told that people shouldn't do that. You're instantly told you should not strive to be similar to God. Would God be pleased if people, who he claims were created in his own image, would try to be similar to God? Of course he would be pleased if every man tried to fulfill his image. Yet, for monkeys in university it is told to do just the opposite! What are the odds! The pattern, which could easily solve most complex problems in the most concise and elegant way, given that you represent all your problems as single database of data (the dreaded God object), where you could easily analyse and check everything for consistency is discouraged from being used so software devs would keep being miserably stupid with 99 programming languages they have to learn and drowning in problems of diverse dynamic garbage interoperating with each other.

That being said, make sure masculine plane figures everything out, so there would be utter simplicity and beauty in the feminine plane, just as it is a natural and the perfect divine way to do this as is evident in all of creation.

Good day bois!
#16
Today I want to talk about another issue leftist software developers today mess up. The wording "Proudly found elsewhere", "Humble thyself and reuse", "Trust libraries written by experts" etc.

I want to explain why this approach becomes meaningless the more mature and old your project is.

You see, when you want to start a project you are attacked by countless choices for a web framework, databases, queues, infra management tools and what not. Examples seem sweet, "Look at this common case, so little code, so shiny! Use me, this framework and be productive and happy!". Every framework offers its own abstractions which it deals with and shows these as beautiful.

Devil is in the details. Now ask yourself, are developers making their frameworks make them to you? No, they make it for a group of people. And that group of people can vary wildly in what they use. Hence, any third party framework can only be generic to the lowest common denominator which satisfies a subset of people. We discussed in specific vs generic thesis how generic things will never be perfectly simple since they are not specific enough for the problem at hand. You can cut salami, wood and bang nails with an axe, but axe would be a generic tool. What you want specifically for the most convenient job is a knife for salami, axe for wood and hammer for nails.

So, unsuspecting developers get lured into yet another web framework with all its subtelties and another baggage of knowledge needs to be established in the brain until you become productive. To make matters worse, if the company becomes successful, it becomes painstainkingly obvious that the framework was never intended for multimillion lines of code, like ruby on rails. Having to maintain millions of lines of code written with dynamically typed language would cause me to become suicidal. But it just becomes too late, and people start huge projects, to split their dear monolith, no refactorings are ever guaranteed to succeed in ruby and the little framework that started so shiny with "look ma, so little code" becomes unbearable, bug ridden burden to the entire company, simply because, people who started with the framework didn't know any better, had no hindsight, and the entire company has to suffer because of early poor technology choices.

What is the alternative you ask? Glad you asked! The alternative, is going to the complete opposite spectrum, which is the pattern. Owning most of your abstractions, like infra management tools, your web framework, your frontend reactive framework. And that sounds crazy at first glance, to someone who doesn't know the power of the pattern and how it makes all of your abstractions much simpler then you'll get anywhere else just because they solve more specific problem to your needs.

The only reason I'd ever pick a generic framework like rails is for short term projects, or prototyping, if you want to get up to speed to see if your project can be successful to begin with. Then, as soon as I know that we're dealing in the long term game I'd start working on the pattern solution for the company ASAP.

You see, it is not obvious to start with the pattern, to own your abstractions. But once you get there, and you have a successful company with the pattern, and you deliver stuff so fast and correctly that everyone's head is spinning and you solve such mountains of problems which little strokes of code that work with your well defined data - no generic framework will ever be able to compete with that.

Which generic framework will offer you at a stroke, in few lines of code to, say:
1. declare a new application
2. declare which typesafe queues it will use
3. declare which typesafe database interactions it will perform
4. have it instantly all monitored according to the abstractions the app uses
5. deploy it in production and it interacts with the rest of your ecosystem correctly the first time

The answer is none, all needs to be done by hand if you take up some used up third party bycicle. And it is error prone and unproductive. The pattern can do all that, but your typesafe rock solid abstractions have to be built, which takes some time for your specific solution, but the benefits will be enjoyed forevermore. You can even have your team names in the pattern and assign enum on which team is responsible for what service. The sky is the limit of what can be done with the pattern.

And every reasonably sized company ought to have their own meta executable with the pattern with their specific use cases. For instance, the pattern of a 3d game developer will be radically different from the pattern of web application shop company. But in their own right, since their meta executable is specific to them, you are then free to not bend to the wills any framework tries to impose on you, but what will be best for the company.

Imagine checking just in one executable that entire network that spans any number of datacenters that no switches have loops, that there are no duplicate ips, that there are no duplicate ports on any server you have, that on any given server you do not exceed declared RAM capacity for what applications will be running. Imagine enforcing via iptables rules that service a can only talk to service b only with typesafe interfaces. All ran in few milliseconds, without spinning up servers in the cloud, just for the fact that you have your problems defined as data and you can reap all the benefits of having complete and total control and knowledge about your entire infrastructure. Don't like some abstraction? Delete and refactor your entire infrastructure at once and be done! No need to synchronize and think about 5 different endpoints that will not work once you shutdown the service.

This is unbeatable. People narrow down their projects like nutjobs, they create service to control dns but it doesn't work with anything else. Then they create more crappy, narrow scope services for orchestration, for network proxy, for CI and nothing ever works together and everyone needs to patch that garbage day and night and praying everything will work.

Why not have all that data, about your services, about your network, infrastructure, databases, their tables and their queries in one place where meta executable could ensure everything is working perfectly together? Leftist degenerate mindsets of today will never figure it out on their own.

So, for any longer term project, you should build the pattern with specific abstractions to you and have perfectly bonded infrastructure to your company. The initial cost will be greater than starting with out of the box framework, but once you get through a steep start of building abstractions you'll have absolute control over your project and abstractions that blow out any third party garbage out of the water. The start with the pattern is slower but the rewards are infinite.

I'll just illustrate what productivity looks with the pattern as the project ages and matures versus taking some garbage off the shelf which was never customly tailored for your company specifically



Have a good day, bois.
#17
My Rants / MOVED: What actually matters
October 24, 2021, 04:08:10 PM
#18
My Rants / MOVED: Dynamism is Cancer
October 24, 2021, 04:08:01 PM
#19
Natural Philosophy / MOVED: Captain Hindsight
October 24, 2021, 04:07:34 PM
#20
Development Tips / Captain Hindsight
September 16, 2021, 03:23:32 PM
Today I want to talk the most foolproof and rock solid way to predict the future - the hindsight.

It may sound obvious, but if something is obvious, has obvious advantages and yet not many people use it and believe the benefits of it, maybe it is not that obvious?

Today a lot of software developers start building complex abstractions, especially in OOP, without having a clue what practical needs actually are. I'm talking mostly about Java projects, which abuse tons of interfaces like I mentioned in specific vs generic thesis.

The problem is not wanting to abstract something to high levels. The wish itself is amazing and is core principle of the pattern which solves tons of problems that cannot be solved by 99% software engineers today.

The problem is that people miss the abstractions, they build them without hindsight of do's and dont's to arrive at the simplest possible solution to the problem. What is inevitable, that by spending time on board and designing something that looks good in imagination yet is quite a flop in reality, because they don't have hindsight.

How to build the abstractions perfectly by acquiring the hindsight?

Do not build the abstractions right from the start. Before I had the pattern which allows me to solve any programming problem in the most concise elegant and most efficient way I didn't have abstractions.

Say, today, I define typesafe rest endpoints and frontend code gets generated and I implement typesafe functions in the backend. How did I think about that? In hindsight, it is obvious. But to arrive at this conclusion, as a poor soul that I was, I simply wrote OCaml code for the backend, and I separately wrote OCaml code to the frontend. I parsed url arguments by hand, was doing mistakes and I just thought to myself - this is bothersome and error prone work. Why can't we generate code that calls the frontend, parses typesafe responses and you don't deal with json at all?

So I did, I did not have this powerful abstraction at the start. I was doing that work by hand, then there was actual, practical need for the abstraction and then I built it and enjoyed the benefits ever since.

Same happened to me when interacting with postgres. Yes, OCaml is amazing, typesafe, as long as you work in its typesafe plane. But, if you use database, you send a string which is not typechecked to the database, hence, you must run the code that uses database to know it will work. So, I had OCaml, that is wonderful language, yet I am suffering from pitfalls of dynamically typed languages I cannot stand by using plain SQL in OCaml code. I didn't want to write tons of tests either like ruby nutjobs do.

Again, from this practical need, I decided to solve this problem with the pattern, every interaction with database via SQL queries must be defined as data and ran against test data with test arguments to ensure query succeeds and returns results. Not only that, I went step further, I didn't restrict functions that were to be generated to just return bunch of strings you have to parse - I made sure all the results from generated code were parsed into typesafe OCaml types.

So then, I brought database into OCaml world, I write SQL queries that are checked in meta executable for correctness and generate typesafe functions that accept typesafe labeled arguments and also return typesafe results of array of structs. From OCaml standpoint, I completely eliminated risks of using raw SQL strings in OCaml and I am in wonderful typesafe OCaml land again.

The need for both of these abstractions arose from hindsight. Not to end up like Java projects, I NEVER BUILD ABSTRACTIONS BEFORE I KNOW I PRACTICALLY NEED THEM. I do the work by hand in the start, once I see I copy paste a lot of stuff that is mostly repeating, at that point I know what I can abstract and what code I can generate and hence I can never make mistake of producing useless unneeded abstractions.

Or, think of Java vs C# - Java was the first one to make all the mistakes and C# did everything better. Or think of C++ vs Rust - Rust had tons of hindsight about bad practices of C++ and eliminated them.

It doesn't matter whose hindsight you use, actually, to use someone elses mistakes to your advantage is cheaper. But, with things like the pattern, as I am the only person I know who does this, and I cannot understand why everyone doesn't do this, I have no hindsight of others to work on. Hence, in such cases, I have to make mistakes myself and then, with hindsight, turn those into abstractions that actually work.

I do not pretend to know everything about good practices with the pattern, I am the first person I know to use it, hence, the area of the pattern is an utterly uncharter experimental territory that needs lots of exploration to be made, and why I created this forum, to help find more fellow pioneers. Am I scared? Not really. You see, everyone else around me is riding a horse and I am the first person to have the very first car. Will it have its quirks? Sure, but I'm already ahead of everyone else that has a horse.

So, long story short, if you want to make practical abstractions, that will be joy to use and will have no risk of becoming overcomplicated, overengineered or useless - always base your abstractions on hindsight, be it someone elses or yours. Don't be an idiot who reads whitepapers all day written by people without practical sense thinking you'll do yourself a favour if you implement something purely theoretical and not based on practical hindsight.

Peace bois.