//--- node db ---// model node ( key id index ( name node_last_ip fields last_net ) index ( name nodes_dis_unk_off_exit_fin_last_success_index fields disqualified unknown_audit_suspended offline_suspended exit_finished_at last_contact_success ) index ( // N.B. the index doesn't have a name which clarifies its purpose because // it was created in the production DBs as it's before being added here name nodes_type_last_cont_success_free_disk_ma_mi_patch_vetted_partial_index fields type last_contact_success free_disk major minor patch vetted_at where node.disqualified = null where node.unknown_audit_suspended = null where node.exit_initiated_at = null where node.release = true where node.last_net != "" ) index ( // N.B. the index doesn't have a name which clarifies its purpose because // it was created in the production DBs as it's before being added here name nodes_dis_unk_aud_exit_init_rel_type_last_cont_success_stored_index fields disqualified unknown_audit_suspended exit_initiated_at release type last_contact_success where node.disqualified = null where node.unknown_audit_suspended = null where node.exit_initiated_at = null where node.release = true ) field id blob // address is how to contact the node, this can be a hostname or IP and it contains the port field address text ( updatable, default "" ) // TODO: use compressed format // last_net is the /24 subnet of the IP field last_net text ( updatable ) field last_ip_port text ( updatable, nullable ) field country_code text ( updatable, nullable ) field protocol int ( updatable, default 0 ) field type int ( updatable, default 0 ) field email text ( updatable ) field wallet text ( updatable ) // TODO: use compressed format field wallet_features text ( updatable, default "" ) field free_disk int64 ( updatable, default -1 ) field piece_count int64 ( autoinsert, updatable, default 0 ) field major int64 ( updatable, default 0 ) field minor int64 ( updatable, default 0 ) field patch int64 ( updatable, default 0 ) field hash text ( updatable, default "" ) field timestamp timestamp ( updatable, default "0001-01-01 00:00:00+00" ) field release bool ( updatable, default false ) field latency_90 int64 ( updatable, default 0 ) field vetted_at timestamp ( updatable, nullable ) field created_at timestamp ( autoinsert, default current_timestamp ) field updated_at timestamp ( autoinsert, autoupdate, default current_timestamp ) field last_contact_success timestamp ( updatable, default "epoch" ) field last_contact_failure timestamp ( updatable, default "epoch" ) // node is disqualified when it fails too many audits or is offline for too long field disqualified timestamp ( updatable, nullable ) field disqualification_reason int ( updatable, nullable ) // node is placed under inspection when it has too many unknown-error audits // renamed column from suspended field unknown_audit_suspended timestamp ( updatable, nullable ) // node is considered unhealthy if it is offline for too many audits field offline_suspended timestamp ( updatable, nullable ) // once a node becomes offline_suspended, mark it as under review so we check it again later field under_review timestamp ( updatable, nullable ) field exit_initiated_at timestamp ( updatable, nullable ) field exit_loop_completed_at timestamp ( updatable, nullable ) field exit_finished_at timestamp ( updatable, nullable ) field exit_success bool ( updatable, default false ) field contained timestamp ( updatable, nullable ) field last_offline_email timestamp ( updatable, nullable ) field last_software_update_email timestamp ( updatable, nullable ) field noise_proto int ( updatable, nullable ) field noise_public_key blob ( updatable, nullable ) ) update node ( where node.id = ? ) update node ( where node.id = ? noreturn ) update node ( where node.id = ? where node.disqualified = null where node.exit_finished_at = null noreturn ) // "Get" query; fails if node not found read one ( select node where node.id = ? ) read all ( select node.id ) read paged ( select node ) read all ( select node.id node.piece_count where node.piece_count != 0 ) // -- node api version -- // model node_api_version ( key id field id blob field api_version int ( updatable ) field created_at timestamp ( autoinsert ) field updated_at timestamp ( autoinsert, autoupdate ) ) create node_api_version ( noreturn replace ) read has ( select node_api_version where node_api_version.id = ? where node_api_version.api_version >= ? ) update node_api_version ( where node_api_version.id = ? where node_api_version.api_version < ? noreturn ) //-- Node Events --// model node_event ( key id index ( name node_events_email_event_created_at_index fields email event created_at where node_event.email_sent = null ) field id blob field email text field node_id blob field event int field created_at timestamp ( default current_timestamp ) field last_attempted timestamp ( nullable, updatable ) field email_sent timestamp ( nullable, updatable ) ) create node_event() read one ( select node_event where node_event.id = ? ) read first ( select node_event where node_event.email = ? where node_event.event = ? orderby desc node_event.created_at ) delete node_event ( where node_event.created_at < ? )