)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"b63e5695b3b2fcffc68419d2676fae3bca0f0085","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"ff0ee4b1_0036f13a","updated":"2022-10-11 09:43:30.000000000","message":"This has been cooking on my git checkout for too long enough. Let\u0027s go.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"}],"cloud/bmaas/bmdb/model/migrations/1662136250_initial.up.sql":[{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":19,"context_line":"    session_runtime_info STRING NOT NULL,"},{"line_number":20,"context_line":"    -- Time at which this session was created."},{"line_number":21,"context_line":"    session_created_at TIMESTAMPTZ NOT NULL,"},{"line_number":22,"context_line":"    -- Number of seconds for which session_deadline (counting from now())"},{"line_number":23,"context_line":"    -- is bumped up every time the session is poked."},{"line_number":24,"context_line":"    session_interval_seconds INT NOT NULL,"},{"line_number":25,"context_line":"    -- Deadline at which this session should not be considered valid anymore."}],"source_content_type":"text/x-sql","patch_set":4,"id":"07ec082b_62a23309","line":22,"range":{"start_line":22,"start_character":25,"end_line":22,"end_character":28},"updated":"2022-10-11 13:59:24.000000000","message":"Drop that `for`? It makes it more confusing IMO.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":true,"context_lines":[{"line_number":19,"context_line":"    session_runtime_info STRING NOT NULL,"},{"line_number":20,"context_line":"    -- Time at which this session was created."},{"line_number":21,"context_line":"    session_created_at TIMESTAMPTZ NOT NULL,"},{"line_number":22,"context_line":"    -- Number of seconds for which session_deadline (counting from now())"},{"line_number":23,"context_line":"    -- is bumped up every time the session is poked."},{"line_number":24,"context_line":"    session_interval_seconds INT NOT NULL,"},{"line_number":25,"context_line":"    -- Deadline at which this session should not be considered valid anymore."}],"source_content_type":"text/x-sql","patch_set":4,"id":"70e4da1a_13719381","line":22,"range":{"start_line":22,"start_character":25,"end_line":22,"end_character":28},"in_reply_to":"07ec082b_62a23309","updated":"2022-10-17 17:11:23.000000000","message":"How about `with`?","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1da37a3c7f75555cc9aeb14ca5c27600f22788fa","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    session_runtime_info STRING NOT NULL,"},{"line_number":20,"context_line":"    -- Time at which this session was created."},{"line_number":21,"context_line":"    session_created_at TIMESTAMPTZ NOT NULL,"},{"line_number":22,"context_line":"    -- Number of seconds for which session_deadline (counting from now())"},{"line_number":23,"context_line":"    -- is bumped up every time the session is poked."},{"line_number":24,"context_line":"    session_interval_seconds INT NOT NULL,"},{"line_number":25,"context_line":"    -- Deadline at which this session should not be considered valid anymore."}],"source_content_type":"text/x-sql","patch_set":4,"id":"396aac89_f40091f3","line":22,"range":{"start_line":22,"start_character":25,"end_line":22,"end_character":28},"in_reply_to":"264113a0_31679bc2","updated":"2022-10-24 14:30:47.000000000","message":"Done","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2ef6421776766310b7b18dd785026ad89d15a050","unresolved":true,"context_lines":[{"line_number":19,"context_line":"    session_runtime_info STRING NOT NULL,"},{"line_number":20,"context_line":"    -- Time at which this session was created."},{"line_number":21,"context_line":"    session_created_at TIMESTAMPTZ NOT NULL,"},{"line_number":22,"context_line":"    -- Number of seconds for which session_deadline (counting from now())"},{"line_number":23,"context_line":"    -- is bumped up every time the session is poked."},{"line_number":24,"context_line":"    session_interval_seconds INT NOT NULL,"},{"line_number":25,"context_line":"    -- Deadline at which this session should not be considered valid anymore."}],"source_content_type":"text/x-sql","patch_set":4,"id":"264113a0_31679bc2","line":22,"range":{"start_line":22,"start_character":25,"end_line":22,"end_character":28},"in_reply_to":"70e4da1a_13719381","updated":"2022-10-19 19:47:50.000000000","message":"by?","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":22,"context_line":"    -- Number of seconds for which session_deadline (counting from now())"},{"line_number":23,"context_line":"    -- is bumped up every time the session is poked."},{"line_number":24,"context_line":"    session_interval_seconds INT NOT NULL,"},{"line_number":25,"context_line":"    -- Deadline at which this session should not be considered valid anymore."},{"line_number":26,"context_line":"    session_deadline TIMESTAMPTZ NOT NULL"},{"line_number":27,"context_line":");"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-sql","patch_set":4,"id":"0a492dd3_7dd4601b","line":25,"range":{"start_line":25,"start_character":16,"end_line":25,"end_character":18},"updated":"2022-10-11 13:59:24.000000000","message":"after?","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    -- Number of seconds for which session_deadline (counting from now())"},{"line_number":23,"context_line":"    -- is bumped up every time the session is poked."},{"line_number":24,"context_line":"    session_interval_seconds INT NOT NULL,"},{"line_number":25,"context_line":"    -- Deadline at which this session should not be considered valid anymore."},{"line_number":26,"context_line":"    session_deadline TIMESTAMPTZ NOT NULL"},{"line_number":27,"context_line":");"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-sql","patch_set":4,"id":"e3dff0e9_19921856","line":25,"range":{"start_line":25,"start_character":16,"end_line":25,"end_character":18},"in_reply_to":"0a492dd3_7dd4601b","updated":"2022-10-17 17:11:23.000000000","message":"Done","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":26,"context_line":"    session_deadline TIMESTAMPTZ NOT NULL"},{"line_number":27,"context_line":");"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"-- Work items map a session performing a given process into a machine. These"},{"line_number":30,"context_line":"-- are optionally created by components to indicate some long-running process"},{"line_number":31,"context_line":"-- being performed on a machine, and will lock out the same process from being"},{"line_number":32,"context_line":"-- run simultaneously, eg. in a concurrently running instance of the same"}],"source_content_type":"text/x-sql","patch_set":4,"id":"54602ade_c1d0bf3c","line":29,"range":{"start_line":29,"start_character":55,"end_line":29,"end_character":69},"updated":"2022-10-11 13:59:24.000000000","message":"to one or more machines? As far as I can see a session can be linked to multiple work items on multiple machines.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":true,"context_lines":[{"line_number":26,"context_line":"    session_deadline TIMESTAMPTZ NOT NULL"},{"line_number":27,"context_line":");"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"-- Work items map a session performing a given process into a machine. These"},{"line_number":30,"context_line":"-- are optionally created by components to indicate some long-running process"},{"line_number":31,"context_line":"-- being performed on a machine, and will lock out the same process from being"},{"line_number":32,"context_line":"-- run simultaneously, eg. in a concurrently running instance of the same"}],"source_content_type":"text/x-sql","patch_set":4,"id":"c72d55a6_5178d231","line":29,"range":{"start_line":29,"start_character":55,"end_line":29,"end_character":69},"in_reply_to":"54602ade_c1d0bf3c","updated":"2022-10-17 17:11:23.000000000","message":"Rewrote comment, please take a look if it\u0027s clearer now.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2ef6421776766310b7b18dd785026ad89d15a050","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    session_deadline TIMESTAMPTZ NOT NULL"},{"line_number":27,"context_line":");"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"-- Work items map a session performing a given process into a machine. These"},{"line_number":30,"context_line":"-- are optionally created by components to indicate some long-running process"},{"line_number":31,"context_line":"-- being performed on a machine, and will lock out the same process from being"},{"line_number":32,"context_line":"-- run simultaneously, eg. in a concurrently running instance of the same"}],"source_content_type":"text/x-sql","patch_set":4,"id":"13bbd8c6_0f62a1d3","line":29,"range":{"start_line":29,"start_character":55,"end_line":29,"end_character":69},"in_reply_to":"c72d55a6_5178d231","updated":"2022-10-19 19:47:50.000000000","message":"Done","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":40,"context_line":"    session_id UUID NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE,"},{"line_number":41,"context_line":"    -- Human-readable process name."},{"line_number":42,"context_line":"    process STRING NOT NULL,"},{"line_number":43,"context_line":"    UNIQUE (machine_id, process),"},{"line_number":44,"context_line":"    CONSTRAINT \"primary\" PRIMARY KEY (machine_id, session_id, process)"},{"line_number":45,"context_line":");"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-sql","patch_set":4,"id":"6906c9c4_832573b1","line":43,"range":{"start_line":43,"start_character":5,"end_line":43,"end_character":33},"updated":"2022-10-11 13:59:24.000000000","message":"Considering that `process` is an (unbounded) string I think this would be better left out. When making changes this could unexpectedly bite us as it invites people to rely on it.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2ef6421776766310b7b18dd785026ad89d15a050","unresolved":true,"context_lines":[{"line_number":40,"context_line":"    session_id UUID NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE,"},{"line_number":41,"context_line":"    -- Human-readable process name."},{"line_number":42,"context_line":"    process STRING NOT NULL,"},{"line_number":43,"context_line":"    UNIQUE (machine_id, process),"},{"line_number":44,"context_line":"    CONSTRAINT \"primary\" PRIMARY KEY (machine_id, session_id, process)"},{"line_number":45,"context_line":");"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-sql","patch_set":4,"id":"9065ee67_be94ef19","line":43,"range":{"start_line":43,"start_character":5,"end_line":43,"end_character":33},"in_reply_to":"11015b04_8240878a","updated":"2022-10-19 19:47:50.000000000","message":"Are there significant disadvantages to using an enum? An enum would IMO be much better if we\u0027re going to rely on it as a unique thing.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":true,"context_lines":[{"line_number":40,"context_line":"    session_id UUID NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE,"},{"line_number":41,"context_line":"    -- Human-readable process name."},{"line_number":42,"context_line":"    process STRING NOT NULL,"},{"line_number":43,"context_line":"    UNIQUE (machine_id, process),"},{"line_number":44,"context_line":"    CONSTRAINT \"primary\" PRIMARY KEY (machine_id, session_id, process)"},{"line_number":45,"context_line":");"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-sql","patch_set":4,"id":"11015b04_8240878a","line":43,"range":{"start_line":43,"start_character":5,"end_line":43,"end_character":33},"in_reply_to":"6906c9c4_832573b1","updated":"2022-10-17 17:11:23.000000000","message":"This uniqueness is critical to ensure that a given process isn\u0027t being applied to a machine twice in parallel.\n\nWe could turn the process into a STRING(N), or we could even define it as cockroachdb enums (as they now exist). But getting rid of this UNIQUE would change the intended use of this design significantly.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1da37a3c7f75555cc9aeb14ca5c27600f22788fa","unresolved":false,"context_lines":[{"line_number":40,"context_line":"    session_id UUID NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE,"},{"line_number":41,"context_line":"    -- Human-readable process name."},{"line_number":42,"context_line":"    process STRING NOT NULL,"},{"line_number":43,"context_line":"    UNIQUE (machine_id, process),"},{"line_number":44,"context_line":"    CONSTRAINT \"primary\" PRIMARY KEY (machine_id, session_id, process)"},{"line_number":45,"context_line":");"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-sql","patch_set":4,"id":"94b4a824_85063542","line":43,"range":{"start_line":43,"start_character":5,"end_line":43,"end_character":33},"in_reply_to":"9065ee67_be94ef19","updated":"2022-10-24 14:30:47.000000000","message":"Converted to enums. Currently the only defined ones are for unit tests.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"}],"cloud/bmaas/bmdb/sessions.go":[{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":98,"context_line":"//"},{"line_number":99,"context_line":"// When the session becomes invalid (for example due to network partition),"},{"line_number":100,"context_line":"// subsequent attempts to call Transact will fail with ErrSessionExpired. This"},{"line_number":101,"context_line":"// means that the component is responsible for recreating a new Session if a"},{"line_number":102,"context_line":"// previously used one expires."},{"line_number":103,"context_line":"func (c *Connection) StartSession(ctx context.Context) (*Session, error) {"},{"line_number":104,"context_line":"\tintervalSeconds :\u003d 5"}],"source_content_type":"text/x-go","patch_set":4,"id":"321b86ff_7dd7df22","line":101,"range":{"start_line":101,"start_character":18,"end_line":101,"end_character":27},"updated":"2022-10-11 13:59:24.000000000","message":"caller?","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":false,"context_lines":[{"line_number":98,"context_line":"//"},{"line_number":99,"context_line":"// When the session becomes invalid (for example due to network partition),"},{"line_number":100,"context_line":"// subsequent attempts to call Transact will fail with ErrSessionExpired. This"},{"line_number":101,"context_line":"// means that the component is responsible for recreating a new Session if a"},{"line_number":102,"context_line":"// previously used one expires."},{"line_number":103,"context_line":"func (c *Connection) StartSession(ctx context.Context) (*Session, error) {"},{"line_number":104,"context_line":"\tintervalSeconds :\u003d 5"}],"source_content_type":"text/x-go","patch_set":4,"id":"4088f227_a3305b73","line":101,"range":{"start_line":101,"start_character":18,"end_line":101,"end_character":27},"in_reply_to":"321b86ff_7dd7df22","updated":"2022-10-17 17:11:23.000000000","message":"Done","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":162,"context_line":"func (s *Session) maintainHeartbeat(ctx context.Context) {"},{"line_number":163,"context_line":"\t// Internal deadline, used to check whether we haven\u0027t dropped the ball on"},{"line_number":164,"context_line":"\t// performing the updates due to a lot of transient errors."},{"line_number":165,"context_line":"\tdeadline :\u003d time.Now().Add(s.interval)"},{"line_number":166,"context_line":"\tfor {"},{"line_number":167,"context_line":"\t\tif ctx.Err() !\u003d nil {"},{"line_number":168,"context_line":"\t\t\tklog.Infof(\"Session %s: context over, exiting: %v\", s.UUID, ctx.Err())"}],"source_content_type":"text/x-go","patch_set":4,"id":"ed453ab5_a9269c87","line":165,"range":{"start_line":165,"start_character":1,"end_line":165,"end_character":9},"updated":"2022-10-11 13:59:24.000000000","message":"There is an edge case here because Go uses monotonic time for these operations but the database uses UTC which is not continuous. But I think it\u0027s mostly fine as the maximum UTC discontinuity is 1s in both directions and the tolerance is 2.5s with our 5s default. But with smaller values this can become a problem. Hopefully ITU-R finally fixes this in 2023.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2ef6421776766310b7b18dd785026ad89d15a050","unresolved":false,"context_lines":[{"line_number":162,"context_line":"func (s *Session) maintainHeartbeat(ctx context.Context) {"},{"line_number":163,"context_line":"\t// Internal deadline, used to check whether we haven\u0027t dropped the ball on"},{"line_number":164,"context_line":"\t// performing the updates due to a lot of transient errors."},{"line_number":165,"context_line":"\tdeadline :\u003d time.Now().Add(s.interval)"},{"line_number":166,"context_line":"\tfor {"},{"line_number":167,"context_line":"\t\tif ctx.Err() !\u003d nil {"},{"line_number":168,"context_line":"\t\t\tklog.Infof(\"Session %s: context over, exiting: %v\", s.UUID, ctx.Err())"}],"source_content_type":"text/x-go","patch_set":4,"id":"095cbe45_4a6c6b89","line":165,"range":{"start_line":165,"start_character":1,"end_line":165,"end_character":9},"in_reply_to":"859e2359_2ffc16cf","updated":"2022-10-19 19:47:50.000000000","message":"I\u0027ve had a second look at it, specifically looking for things that using Unix nanos would solve and found none. So while this might be an issue, it cannot be solved by doing that. It depends on a bunch of specific behavior like how long time.Sleep(1*time.Second) takes during a leap second and so forth. So let\u0027s just leave it be.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":true,"context_lines":[{"line_number":162,"context_line":"func (s *Session) maintainHeartbeat(ctx context.Context) {"},{"line_number":163,"context_line":"\t// Internal deadline, used to check whether we haven\u0027t dropped the ball on"},{"line_number":164,"context_line":"\t// performing the updates due to a lot of transient errors."},{"line_number":165,"context_line":"\tdeadline :\u003d time.Now().Add(s.interval)"},{"line_number":166,"context_line":"\tfor {"},{"line_number":167,"context_line":"\t\tif ctx.Err() !\u003d nil {"},{"line_number":168,"context_line":"\t\t\tklog.Infof(\"Session %s: context over, exiting: %v\", s.UUID, ctx.Err())"}],"source_content_type":"text/x-go","patch_set":4,"id":"859e2359_2ffc16cf","line":165,"range":{"start_line":165,"start_character":1,"end_line":165,"end_character":9},"in_reply_to":"ed453ab5_a9269c87","updated":"2022-10-17 17:11:23.000000000","message":"Should I move everything to use Go time instead, ie. int64 nanos from epoch and client-side now()?","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":230,"context_line":"// some identified machine. Not more than one process of a given name can run"},{"line_number":231,"context_line":"// against a machine concurrently."},{"line_number":232,"context_line":"//"},{"line_number":233,"context_line":"// Most impure (meaning with side effects within the database itself) BMDB"},{"line_number":234,"context_line":"// transactions should be run this way."},{"line_number":235,"context_line":"func (s *Session) Work(ctx context.Context, machine uuid.UUID, process string, fn func() error) error {"},{"line_number":236,"context_line":"\terr :\u003d model.New(s.connection.db).StartWork(ctx, model.StartWorkParams{"}],"source_content_type":"text/x-go","patch_set":4,"id":"32757710_9ad62301","line":233,"range":{"start_line":233,"start_character":42,"end_line":233,"end_character":48},"updated":"2022-10-11 13:59:24.000000000","message":"outside","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":false,"context_lines":[{"line_number":230,"context_line":"// some identified machine. Not more than one process of a given name can run"},{"line_number":231,"context_line":"// against a machine concurrently."},{"line_number":232,"context_line":"//"},{"line_number":233,"context_line":"// Most impure (meaning with side effects within the database itself) BMDB"},{"line_number":234,"context_line":"// transactions should be run this way."},{"line_number":235,"context_line":"func (s *Session) Work(ctx context.Context, machine uuid.UUID, process string, fn func() error) error {"},{"line_number":236,"context_line":"\terr :\u003d model.New(s.connection.db).StartWork(ctx, model.StartWorkParams{"}],"source_content_type":"text/x-go","patch_set":4,"id":"b2d90bae_02dbcce6","line":233,"range":{"start_line":233,"start_character":42,"end_line":233,"end_character":48},"in_reply_to":"32757710_9ad62301","updated":"2022-10-17 17:11:23.000000000","message":"Yeah, good catch.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2b5ebfc78b6012c471eb1dcc735ab2b18ac0d10b","unresolved":true,"context_lines":[{"line_number":256,"context_line":"\t\tklog.Errorf(\"Finished work: %q on machine %s, session %s\", process, machine, s.UUID)"},{"line_number":257,"context_line":"\t\tif err !\u003d nil \u0026\u0026 !errors.Is(err, s.ctx.Err()) {"},{"line_number":258,"context_line":"\t\t\tklog.Errorf(\"Failed to finish work: %v\", err)"},{"line_number":259,"context_line":"\t\t\tklog.Errorf(\"Closing session out of an abundance of caution\")"},{"line_number":260,"context_line":"\t\t\ts.ctxC()"},{"line_number":261,"context_line":"\t\t}"},{"line_number":262,"context_line":"\t}()"}],"source_content_type":"text/x-go","patch_set":4,"id":"6c5e97c5_f44e4022","line":259,"range":{"start_line":259,"start_character":0,"end_line":259,"end_character":64},"updated":"2022-10-11 13:59:24.000000000","message":"Is there lower-level retry on this? Otherwise this seems kind of quick to kill the entire session.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"2ef6421776766310b7b18dd785026ad89d15a050","unresolved":false,"context_lines":[{"line_number":256,"context_line":"\t\tklog.Errorf(\"Finished work: %q on machine %s, session %s\", process, machine, s.UUID)"},{"line_number":257,"context_line":"\t\tif err !\u003d nil \u0026\u0026 !errors.Is(err, s.ctx.Err()) {"},{"line_number":258,"context_line":"\t\t\tklog.Errorf(\"Failed to finish work: %v\", err)"},{"line_number":259,"context_line":"\t\t\tklog.Errorf(\"Closing session out of an abundance of caution\")"},{"line_number":260,"context_line":"\t\t\ts.ctxC()"},{"line_number":261,"context_line":"\t\t}"},{"line_number":262,"context_line":"\t}()"}],"source_content_type":"text/x-go","patch_set":4,"id":"fa5322cc_39afea7c","line":259,"range":{"start_line":259,"start_character":0,"end_line":259,"end_character":64},"in_reply_to":"50566182_8c9afab3","updated":"2022-10-19 19:47:50.000000000","message":"Ack","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9b439d96cfb9dcfc04ed1e15627c75a2992d9032","unresolved":true,"context_lines":[{"line_number":256,"context_line":"\t\tklog.Errorf(\"Finished work: %q on machine %s, session %s\", process, machine, s.UUID)"},{"line_number":257,"context_line":"\t\tif err !\u003d nil \u0026\u0026 !errors.Is(err, s.ctx.Err()) {"},{"line_number":258,"context_line":"\t\t\tklog.Errorf(\"Failed to finish work: %v\", err)"},{"line_number":259,"context_line":"\t\t\tklog.Errorf(\"Closing session out of an abundance of caution\")"},{"line_number":260,"context_line":"\t\t\ts.ctxC()"},{"line_number":261,"context_line":"\t\t}"},{"line_number":262,"context_line":"\t}()"}],"source_content_type":"text/x-go","patch_set":4,"id":"50566182_8c9afab3","line":259,"range":{"start_line":259,"start_character":0,"end_line":259,"end_character":64},"in_reply_to":"6c5e97c5_f44e4022","updated":"2022-10-17 17:11:23.000000000","message":"As far as I understand this _should_ be fine (eg. this won\u0027t be affected by transaction retries, as CockroachDB will do that for us in a non-transactional query).\n\nThe only thing I\u0027m worried about is spurious transient network errors being a bit too much on this, but I\u0027d like to test that in practice. I think just letting the whole session die (and monitoring that) will let us notice any problems/behavior easier, and then we can implement more granular retries if necessary.","commit_id":"4f870b74c4a40405310b87a54faf53bc5e1e1eee"}]}
