import { Table } from '@google-cloud/bigquery' ; import { InsertableTable } from './infrastructure/table' ; import { HourlyConnectionMetricsReport , HourlyUserConnectionMetricsReport } from './model' ; export interface ConnectionRow { serverId : string ; startTimestamp : string ; endTimestamp : string ; userId : string ; bytesTransferred : number ; countries : string [ ] ; } export class BigQueryConnectionsTable implements InsertableTable < ConnectionRow > { constructor ( private bigqueryTable ) { } async insert ( rows ) { await this . bigqueryTable . insert ( rows ) ; } } export function postConnectionMetrics ( table , report ) { return table . insert ( getConnectionRowsFromReport ( report ) ) ; } function getConnectionRowsFromReport ( report ) { const startTimestampStr = new Date ( report . startUtcMs ) . toISOString ( ) ; const endTimestampStr = new Date ( report . endUtcMs ) . toISOString ( ) ; const rows = [ ] ; for ( const userReport of report . userReports ) { rows . push ( { serverId : report . serverId , startTimestamp : startTimestampStr , endTimestamp : endTimestampStr , userId : userReport . userId , bytesTransferred : userReport . bytesTransferred , countries : userReport . countries } ) ; } return rows ; } export function isValidConnectionMetricsReport ( testObject ) { if ( ! testObject ) { return false ; } const requiredConnectionMetricsFields = [ 'serverId' , 'startUtcMs' , 'endUtcMs' , 'userReports' ] ; for ( const fieldName of requiredConnectionMetricsFields ) { if ( ! testObject [ fieldName ] ) { return false ; } } if ( typeof testObject . serverId !== 'string' ) { return false ; } if ( typeof testObject . startUtcMs !== 'number' || typeof testObject . endUtcMs !== 'number' || testObject . startUtcMs >= testObject . endUtcMs ) { return false ; } if ( ! ( testObject . userReports . length >= 1 ) ) { return false ; } const requiredUserReportFields = [ 'userId' , 'countries' , 'bytesTransferred' ] ; const MIN_BYTES_TRANSFERRED = 0 ; const MAX_BYTES_TRANSFERRED = 1 * Math . pow ( 2 , 40 ) ; for ( const userReport of testObject . userReports ) { for ( const fieldName of requiredUserReportFields ) { if ( ! userReport [ fieldName ] ) { return false ; } } if ( typeof userReport . userId !== 'string' ) { return false ; } if ( typeof userReport . bytesTransferred !== 'number' || userReport . bytesTransferred < MIN_BYTES_TRANSFERRED || userReport . bytesTransferred > MAX_BYTES_TRANSFERRED ) { return false ; } for ( const country of userReport . countries ) { if ( typeof country !== 'string' ) { return false ; } } } return true ; }