<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ceres/model/database.go, branch step-re-ordering</title>
<subtitle>Recipe server for your favorite dishes</subtitle>
<id>https://cgit.xengineering.eu/ceres/atom/model/database.go?h=step-re-ordering</id>
<link rel='self' href='https://cgit.xengineering.eu/ceres/atom/model/database.go?h=step-re-ordering'/>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/'/>
<updated>2024-10-21T19:37:54Z</updated>
<entry>
<title>model: Rename to db.go</title>
<updated>2024-10-21T19:37:54Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-21T19:37:54Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=f917bc9e1973bfc1c6ab56bf1362295f89d687c3'/>
<id>urn:sha1:f917bc9e1973bfc1c6ab56bf1362295f89d687c3</id>
<content type='text'>
The old name database.go did not match the type name DB.
</content>
</entry>
<entry>
<title>model: Refactor public API of DB</title>
<updated>2024-10-21T19:34:31Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-21T19:30:12Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=72601b87ef040a3c6882368ac85c12c1ae705cd2'/>
<id>urn:sha1:72601b87ef040a3c6882368ac85c12c1ae705cd2</id>
<content type='text'>
This commit makes not externally needed methods private and adds error
return values since something like log.Fatal() should be called outside
this package since it is control-flow-related.
</content>
</entry>
<entry>
<title>model: Save int-based schema version in DB</title>
<updated>2024-10-21T19:34:26Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-15T19:23:10Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=118e1c69057e4e7b6ab3e730d5628b4822ed4c4d'/>
<id>urn:sha1:118e1c69057e4e7b6ab3e730d5628b4822ed4c4d</id>
<content type='text'>
Ceres v0.4.0 used the `git describe` output as database schema and
enforced exactly matching versions between the database and the
executable.

This turned out to be not flexible enough. It is way easier to version
the database separately with a simple integer and require the same
database schema version integer between the application and the
database.

This commit implements this new approach.
</content>
</entry>
<entry>
<title>model: Handle schema versions internally by integers</title>
<updated>2024-10-15T18:25:38Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-13T18:34:29Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=1904f50084660ce587a67d49939fd0734fd8a582'/>
<id>urn:sha1:1904f50084660ce587a67d49939fd0734fd8a582</id>
<content type='text'>
This references the database schemas known from the past with integer
values internally. 0 is used for an empty database and 1 for what was
used in ceres version 0.4.0.

The old approach to write the `git describe` output into the database
worked well for released versions but was problematic during
development. A numerical and separate database schema versioning is
easier to handle.
</content>
</entry>
<entry>
<title>model: Simplify DB method signatures</title>
<updated>2024-10-13T18:21:00Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-13T18:21:00Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=5ca945112b5cd7c92eb3b9da81597fcba5256b56'/>
<id>urn:sha1:5ca945112b5cd7c92eb3b9da81597fcba5256b56</id>
<content type='text'>
</content>
</entry>
<entry>
<title>model: Replace global db variable by custom type</title>
<updated>2024-10-13T17:55:38Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-13T17:52:28Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=473052ed8f2c83052ed5b47a7f4cec68ac2621a6'/>
<id>urn:sha1:473052ed8f2c83052ed5b47a7f4cec68ac2621a6</id>
<content type='text'>
Reducing global variables makes it easier to understand functions
independently of the rest of the code.

Adding the new model.DB type as a custom variant of the sql.DB type
makes it possible to write methods for the database which makes the code
way more readable.
</content>
</entry>
<entry>
<title>Introduce xengineering.eu/ceres/model/migrations</title>
<updated>2024-10-13T16:54:18Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-10-13T12:08:26Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=ed19b82335345833c5b8f5446237d559a3657a35'/>
<id>urn:sha1:ed19b82335345833c5b8f5446237d559a3657a35</id>
<content type='text'>
This new package is only for database migrations. All data for Ceres
should be stored inside the SQLite3 database. Thus migrations can always
be executed with functions with the following signature.

    func(tx *sql.Tx) error

Those migration functions should be stored inside the new package.
Bigger SQL code can be stored in *.sql files for better syntax
highlighting. This code is embedded into the final Go executable by
using the embed package.
</content>
</entry>
<entry>
<title>Inject examples only with new --example flag</title>
<updated>2024-05-09T20:37:03Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T20:33:42Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=0ac3cc76b4b6c824c4b3f7a357d40b487984abfb'/>
<id>urn:sha1:0ac3cc76b4b6c824c4b3f7a357d40b487984abfb</id>
<content type='text'>
The default use case should be to not inject example recipes.
</content>
</entry>
<entry>
<title>model: Rename version to execVersion</title>
<updated>2024-05-09T20:12:54Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T20:12:54Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=f7fca11c47224ff28b10a7f41fb76ce0404a0236'/>
<id>urn:sha1:f7fca11c47224ff28b10a7f41fb76ce0404a0236</id>
<content type='text'>
This makes the code easier to understand because there is an executable
version and a database version handled inside that file.
</content>
</entry>
<entry>
<title>model: Require same version for executable and DB</title>
<updated>2024-05-09T20:04:06Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T20:04:06Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=0e8a199d6144fcfab05eb0c8a793073bc53783be'/>
<id>urn:sha1:0e8a199d6144fcfab05eb0c8a793073bc53783be</id>
<content type='text'>
Currently only an empty database and an existing database with the same
version are supported.

Support for migrations based on semantic versioning will be added in
future versions of Ceres.
</content>
</entry>
<entry>
<title>model: Migrate only in empty databases</title>
<updated>2024-05-09T19:59:01Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T19:59:01Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=e5d57f2c4a9f01ac7a2b11c04b932311bd240611'/>
<id>urn:sha1:e5d57f2c4a9f01ac7a2b11c04b932311bd240611</id>
<content type='text'>
</content>
</entry>
<entry>
<title>model: Initial database version injection</title>
<updated>2024-05-09T19:48:56Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T19:48:56Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=ca96df29085f9ca6567cd474d0920e48c6410b42'/>
<id>urn:sha1:ca96df29085f9ca6567cd474d0920e48c6410b42</id>
<content type='text'>
If the database was empty on startup a metadata table with a key and
value row is created.

In addition the Ceres executable version is inserted as value under the
key 'version'.

This allows to detect on not-empty databases which Ceres version was
used before which is the starting point to implement migrations.
</content>
</entry>
<entry>
<title>model: Detect if database is empty</title>
<updated>2024-05-09T19:31:19Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T19:31:19Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=ca19c73b305932a4ef41d31787eabb25f9417a05'/>
<id>urn:sha1:ca19c73b305932a4ef41d31787eabb25f9417a05</id>
<content type='text'>
An empty database requires to add the metadata table with the version
entry to make migrations possible. Thus this detection will be required.
</content>
</entry>
<entry>
<title>model: Wrap migration completely in transaction</title>
<updated>2024-05-09T19:10:50Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T19:10:15Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=2db08f564ddb38e80c79c9338047f4e8f3a977e8'/>
<id>urn:sha1:2db08f564ddb38e80c79c9338047f4e8f3a977e8</id>
<content type='text'>
This makes it more clear that the full migration will be rolled back on
errors.
</content>
</entry>
<entry>
<title>model: Use defer for tx.Rollback()</title>
<updated>2024-05-09T09:13:46Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T09:13:46Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=fd7ee91110cf1de780f3c46822dd69385b3b6318'/>
<id>urn:sha1:fd7ee91110cf1de780f3c46822dd69385b3b6318</id>
<content type='text'>
A committed transaction cannot be rolled back. Using defer to roll back
guarantees that the transaction is always rolled back if not the commit
in the last line of model.Transaction was excuted.

[1]: https://go.dev/doc/database/execute-transactions
</content>
</entry>
<entry>
<title>Restructure database-related functions</title>
<updated>2024-05-09T08:02:00Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-09T08:02:00Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=a2038b0ea35d1466c84e6e04a2e4597fc038815a'/>
<id>urn:sha1:a2038b0ea35d1466c84e6e04a2e4597fc038815a</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Introduce model.Transaction()</title>
<updated>2024-05-08T20:26:00Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-08T19:53:13Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=0ba1a7661a81200db98e40149eef1e39fd22f407'/>
<id>urn:sha1:0ba1a7661a81200db98e40149eef1e39fd22f407</id>
<content type='text'>
It is a very common pattern that some function needs to access the
database and wants to wrap all the actions into one transaction.

The advantage of a transaction is that it is ACID:

- atomic
- consistent
- isolated
- durable

In Go it is required to request a new transaction, execute functionality
on it and handle rollback or commit of this transaction based on the
success of the operation.

All this and the error handling can be written down in the
model.Transaction() function exactly once. The full signature of it is:

	func Transaction(f func(*sql.Tx) error) error

It requires a function or closure passed as argument which takes the
transaction (*sql.Tx) and returns an error which might be nil.

This is very generic. It is applied to:

- injecting test data
- database migrations
- data read requests
- data write requests
</content>
</entry>
<entry>
<title>model: Init database with database path</title>
<updated>2024-05-07T19:25:19Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-07T19:25:19Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=75c1270c86ac17d056161714ac32a57113696d21'/>
<id>urn:sha1:75c1270c86ac17d056161714ac32a57113696d21</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Use default storage path instead of temp dir</title>
<updated>2024-05-01T11:19:05Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-05-01T11:19:05Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=4cc0677b79edeed05ead23def152ac45f35f556d'/>
<id>urn:sha1:4cc0677b79edeed05ead23def152ac45f35f556d</id>
<content type='text'>
</content>
</entry>
<entry>
<title>model: Always pass *sql.Tx to CRUD methods</title>
<updated>2024-04-06T11:12:17Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-04-06T11:12:17Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=f65b11a5b3011f370df5b4d32239225f3708ecd5'/>
<id>urn:sha1:f65b11a5b3011f370df5b4d32239225f3708ecd5</id>
<content type='text'>
When nesting objects like steps into other objects like recipes it is
required to pass a *sql.Tx value to the CRUD methods of the inner
object to be able to roll back the whole transaction.

The top level object used to be responsible for the creation of this
*sql.Tx inside its CRUD methods.

This is now moved to the caller of the CRUD methods (here the HTTP
handler function). The advantage is that all CRUD methods now accept a
*sql.Tx as only argument which makes those methods more consistent.
</content>
</entry>
<entry>
<title>model: Add recipe steps</title>
<updated>2024-03-24T09:10:54Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-03-10T09:59:23Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=ddc6e8e1fb8a4b1dfe8421b12e40b15162ae75f1'/>
<id>urn:sha1:ddc6e8e1fb8a4b1dfe8421b12e40b15162ae75f1</id>
<content type='text'>
This provides the infrastructure to create views and HTTP handlers to
provide recipe steps.
</content>
</entry>
<entry>
<title>model: Crash on failed test recipe injection</title>
<updated>2024-03-24T09:10:54Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-03-12T17:25:48Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=0520cf604c4dc3279d76e1dd4b49c275dd54611e'/>
<id>urn:sha1:0520cf604c4dc3279d76e1dd4b49c275dd54611e</id>
<content type='text'>
This error used to be silent. Since it is just about test recipes and
thus a debugging environment it is best to directly give up and log the
error.
</content>
</entry>
<entry>
<title>model: Create test data with Go instead of SQL</title>
<updated>2024-03-04T19:33:58Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2024-03-03T19:06:40Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=b62c686702622b747ab082b7b12b3e611e1d7e1f'/>
<id>urn:sha1:b62c686702622b747ab082b7b12b3e611e1d7e1f</id>
<content type='text'>
This allows to formulate the test data with an object-based model which
is easier than writing it down in a relational model.
</content>
</entry>
<entry>
<title>model: Inject test data into database</title>
<updated>2023-12-27T12:05:05Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2023-12-27T12:04:26Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=8ce328fafd9b2ad152f0afc16176cf01e1e66669'/>
<id>urn:sha1:8ce328fafd9b2ad152f0afc16176cf01e1e66669</id>
<content type='text'>
This is useful for debugging and testing.
</content>
</entry>
<entry>
<title>model: Add initial SQL migration</title>
<updated>2023-12-27T11:42:25Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2023-12-27T11:39:10Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=e7bbadc8f469d5cbfbc012932c83d1d440b6e8a3'/>
<id>urn:sha1:e7bbadc8f469d5cbfbc012932c83d1d440b6e8a3</id>
<content type='text'>
This provides the basic table structure to the database.
</content>
</entry>
<entry>
<title>model: Implement database connection</title>
<updated>2023-12-27T11:27:53Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2023-12-27T11:14:43Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/ceres/commit/?id=c452ca52b9c18303045db838c6cead62c1454172'/>
<id>urn:sha1:c452ca52b9c18303045db838c6cead62c1454172</id>
<content type='text'>
The already implemented storage folder should contain a sqlite database
to store most parts of the Ceres user data.
</content>
</entry>
</feed>
