2021-12-28 10:25:04 -05:00
"use strict" ;
2021-09-06 13:50:38 -04:00
var g _wants _requests = { } ;
2021-11-03 19:23:20 -04:00
var g _database = new Database ( 'core' ) ;
2021-12-27 14:52:42 -05:00
const k _use _create _history _stream = false ;
2021-09-06 13:50:38 -04:00
2021-10-31 15:39:16 -04:00
function get _latest _sequence _for _author ( author ) {
2021-10-30 17:07:01 -04:00
var sequence = 0 ;
2021-10-31 15:39:16 -04:00
ssb . sqlStream (
2022-02-05 22:28:29 -05:00
'SELECT MAX(sequence) AS sequence FROM messages WHERE author = ?1' ,
2021-10-30 17:07:01 -04:00
[ author ] ,
function ( row ) {
2021-10-31 15:39:16 -04:00
if ( row . sequence ) {
2021-12-27 14:52:42 -05:00
sequence = row . sequence ;
2021-10-31 15:39:16 -04:00
}
2021-10-30 17:07:01 -04:00
} ) ;
return sequence ;
}
2021-12-22 14:57:34 -05:00
function storeMessage ( message ) {
var payload = message . message . value ? message . message . value : message . message ;
if ( typeof ( payload ) == 'object' ) {
ssb . storeMessage ( payload ) ;
}
}
2022-11-02 19:34:44 -04:00
ssb . addEventListener ( 'connections' , function on _connections _changed ( change , connection ) {
2021-09-06 13:50:38 -04:00
if ( change == 'add' ) {
2021-10-31 15:39:16 -04:00
var sequence = get _latest _sequence _for _author ( connection . id ) ;
2021-12-27 14:52:42 -05:00
if ( k _use _create _history _stream ) {
connection . send _json ( { 'name' : [ 'createHistoryStream' ] , 'type' : 'source' , 'args' : [ { 'id' : connection . id , 'seq' : sequence , 'live' : true , 'keys' : false } ] } , storeMessage ) ;
2022-07-31 15:01:08 -04:00
var identities = ssb . getAllIdentities ( ) ;
2022-12-31 16:44:48 -05:00
ssb . followingDeep ( identities , 2 ) . then ( function ( ids ) {
2021-12-27 14:52:42 -05:00
for ( let id of ids ) {
2022-07-31 15:01:08 -04:00
if ( identities . indexOf ( id ) != - 1 ) {
2021-12-27 14:52:42 -05:00
continue ;
}
var sequence = get _latest _sequence _for _author ( id ) ;
connection . send _json ( { 'name' : [ 'createHistoryStream' ] , 'type' : 'source' , 'args' : [ { 'id' : id , 'seq' : sequence , 'live' : true , 'keys' : false } ] } , storeMessage ) ;
}
} ) ;
} else {
if ( connection . is _client ) {
2022-11-11 21:00:49 -05:00
connection . send _json ( { "name" : [ "ebt" , "replicate" ] , "args" : [ { "version" : 3 , "format" : "classic" } ] , "type" : "duplex" } , ebtReplicateClient ) ;
2021-12-27 14:52:42 -05:00
}
}
2021-09-06 13:50:38 -04:00
} else if ( change == 'remove' ) {
2021-11-03 18:15:46 -04:00
print ( 'REMOVE' , connection . id ) ;
2021-09-06 13:50:38 -04:00
delete g _wants _requests [ connection . id ] ;
} else {
2021-11-03 18:15:46 -04:00
print ( 'CHANGE' , change ) ;
2021-09-06 13:50:38 -04:00
}
} ) ;
2021-12-27 14:52:42 -05:00
function ebtReplicateSendClock ( request , have ) {
2022-07-31 15:01:08 -04:00
var identities = ssb . getAllIdentities ( ) ;
2021-12-27 14:52:42 -05:00
var message = { } ;
2022-01-22 15:13:14 -05:00
var last _sent = request . connection . sent _clock || { } ;
2022-12-31 16:44:48 -05:00
var ids = ssb . followingDeep ( identities , 2 ) . concat ( [ request . connection . id ] ) ;
2022-01-22 15:47:10 -05:00
if ( ! Object . keys ( last _sent ) . length ) {
2022-01-22 15:13:14 -05:00
for ( let id of ids ) {
2022-02-05 22:49:47 -05:00
message [ id ] = get _latest _sequence _for _author ( id ) ;
2022-01-22 15:13:14 -05:00
}
2021-12-27 14:52:42 -05:00
}
2021-12-28 10:25:04 -05:00
for ( let id of Object . keys ( have ) ) {
if ( message [ id ] === undefined ) {
var sequence = get _latest _sequence _for _author ( id ) ;
message [ id ] = sequence ? sequence : - 1 ;
}
}
2021-12-27 14:52:42 -05:00
var to _send = { }
2022-02-10 21:44:27 -05:00
var offset = Math . floor ( Math . random ( ) * ids . length ) ;
for ( var i = 0 ; i < ids . length ; i ++ ) {
var id = ids [ ( i + offset ) % ids . length ] ;
2021-12-27 14:52:42 -05:00
if ( last _sent [ id ] === undefined || message [ id ] > last _sent [ id ] ) {
last _sent [ id ] = to _send [ id ] = message [ id ] === - 1 ? - 1 : message [ id ] << 1 ;
}
2021-12-28 10:25:04 -05:00
if ( Object . keys ( to _send ) . length >= 32 ) {
request . send _json ( to _send ) ;
to _send = { } ;
}
2021-12-27 14:52:42 -05:00
}
request . connection . sent _clock = last _sent ;
if ( Object . keys ( to _send ) . length ) {
request . send _json ( to _send ) ;
}
}
function formatMessage ( row ) {
2022-02-02 21:00:05 -05:00
if ( row . sequence _before _author ) {
return {
previous : row . previous ,
sequence : row . sequence ,
author : row . author ,
timestamp : row . timestamp ,
hash : row . hash ,
content : JSON . parse ( row . content ) ,
signature : row . signature ,
} ;
} else {
return {
previous : row . previous ,
author : row . author ,
sequence : row . sequence ,
timestamp : row . timestamp ,
hash : row . hash ,
content : JSON . parse ( row . content ) ,
signature : row . signature ,
} ;
}
2021-12-27 14:52:42 -05:00
}
function ebtReplicateRegisterMessageCallback ( request ) {
ssb . addEventListener ( 'message' , function ( message _id ) {
2022-12-31 13:59:29 -05:00
if ( request . connection . send _clock ) {
ssb . sqlStream (
'SELECT previous, author, id, sequence, timestamp, hash, content, signature FROM messages WHERE id = ?1' ,
[ message _id ] ,
function ( row ) {
if ( request . connection . send _clock [ row . author ] < row . sequence ) {
request . send _json ( formatMessage ( row ) ) ;
}
} ) ;
}
2021-12-27 14:52:42 -05:00
} ) ;
}
function ebtReplicateCommon ( request ) {
if ( request . message . author ) {
storeMessage ( request ) ;
} else {
ebtReplicateSendClock ( request , request . message ) ;
2022-12-31 13:59:29 -05:00
if ( ! request . connection . send _clock ) {
request . connection . send _clock = { } ;
}
2021-12-27 14:52:42 -05:00
for ( let id of Object . keys ( request . message ) ) {
if ( request . message [ id ] >= 0 && ( request . message [ id ] & 1 ) == 0 ) {
2022-12-31 13:59:29 -05:00
request . connection . send _clock [ id ] = request . message [ id ] >> 1 ;
2021-12-27 14:52:42 -05:00
ssb . sqlStream (
'SELECT previous, author, id, sequence, timestamp, hash, content, signature FROM messages WHERE author = ?1 AND sequence >= ?2 ORDER BY sequence' ,
[ id , request . message [ id ] >> 1 ] ,
function ( row ) {
request . send _json ( formatMessage ( row ) ) ;
2022-12-31 13:59:29 -05:00
request . connection . send _clock [ id ] = row . sequence ;
2021-12-27 14:52:42 -05:00
} ) ;
2022-12-31 13:59:29 -05:00
} else {
delete request . connection . send _clock [ id ] ;
2021-12-27 14:52:42 -05:00
}
}
}
}
function ebtReplicateClient ( request ) {
2022-11-11 21:00:49 -05:00
if ( request . message ? . name !== 'Error' ) {
if ( ! request . connection . message _registered ) {
ebtReplicateRegisterMessageCallback ( request ) ;
request . connection . message _registered = true ;
}
ebtReplicateCommon ( request ) ;
2021-12-27 14:52:42 -05:00
}
}
function ebtReplicateServer ( request ) {
ebtReplicateRegisterMessageCallback ( request ) ;
ebtReplicateSendClock ( request , { } ) ;
request . more ( ebtReplicateCommon ) ;
}
ssb . addRpc ( [ 'ebt' , 'replicate' ] , ebtReplicateServer ) ;
2021-11-07 17:28:58 -05:00
ssb . addRpc ( [ 'createHistoryStream' ] , function ( request ) {
2023-01-03 21:59:35 -05:00
if ( ! request ? . args ) {
print ( 'missing request.args in createHistoryStream' ) ;
}
2021-09-06 13:50:38 -04:00
var id = request . args [ 0 ] . id ;
var seq = request . args [ 0 ] . seq ;
2021-11-05 22:10:13 -04:00
var keys = request . args [ 0 ] . keys || request . args [ 0 ] . keys === undefined ;
2021-11-10 19:05:07 -05:00
function sendMessage ( row ) {
if ( keys ) {
var message = {
key : row . id ,
2022-02-02 21:00:05 -05:00
value : formatMessage ( row ) ,
2021-11-10 19:05:07 -05:00
timestamp : row . timestamp ,
} ;
} else {
2022-02-02 21:00:05 -05:00
var message = formatMessage ( row ) ;
2021-11-10 19:05:07 -05:00
}
request . send _json ( message ) ;
}
ssb . sqlStream (
2022-02-02 21:00:05 -05:00
'SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE author = ?1 AND sequence >= ?2 ORDER BY sequence' ,
2021-11-10 19:05:07 -05:00
[ id , seq ? ? 0 ] ,
sendMessage ) ;
2021-12-20 12:00:25 -05:00
ssb . addEventListener ( 'message' , function ( message _id ) {
2021-11-10 19:05:07 -05:00
ssb . sqlStream (
2022-02-02 21:00:05 -05:00
'SELECT previous, author, id, sequence, timestamp, hash, content, signature, sequence_before_author FROM messages WHERE id = ?1 AND author = ?2' ,
2021-12-27 14:52:42 -05:00
[ message _id , id ] ,
2021-12-20 12:00:25 -05:00
function ( row ) {
2021-12-27 14:52:42 -05:00
sendMessage ( row ) ;
2021-12-20 12:00:25 -05:00
} ) ;
2021-11-10 19:05:07 -05:00
} ) ;
2021-09-06 13:50:38 -04:00
} ) ;