Add instance stats to object returned by /api/v1/instance

This commit is contained in:
silverpill 2022-10-04 20:50:00 +00:00
parent fa49e2b4c2
commit 6fd0c16997
7 changed files with 79 additions and 8 deletions

View file

@ -1038,6 +1038,19 @@ components:
registrations: registrations:
description: Whether registrations are enabled. description: Whether registrations are enabled.
type: boolean type: boolean
stats:
description: Statistics about how much information the instance contains.
type: object
properties:
user_count:
description: Users registered on this instance
type: integer
status_count:
description: Statuses authored by users on instance.
type: integer
domain_count:
description: Domains federated with this instance.
type: integer
login_message: login_message:
description: Login message for signer. description: Login message for signer.
type: string type: string

View file

@ -5,6 +5,13 @@ use crate::config::{BlockchainConfig, Config};
use crate::ethereum::contracts::ContractSet; use crate::ethereum::contracts::ContractSet;
use crate::mastodon_api::MASTODON_API_VERSION; use crate::mastodon_api::MASTODON_API_VERSION;
#[derive(Serialize)]
struct InstanceStats {
user_count: i64,
status_count: i64,
domain_count: i64,
}
#[derive(Serialize)] #[derive(Serialize)]
struct BlockchainFeatures { struct BlockchainFeatures {
minter: bool, minter: bool,
@ -27,6 +34,7 @@ pub struct InstanceInfo {
description: String, description: String,
version: String, version: String,
registrations: bool, registrations: bool,
stats: InstanceStats,
login_message: String, login_message: String,
post_character_limit: usize, post_character_limit: usize,
@ -43,7 +51,13 @@ fn get_full_api_version(version: &str) -> String {
} }
impl InstanceInfo { impl InstanceInfo {
pub fn create(config: &Config, maybe_blockchain: Option<&ContractSet>) -> Self { pub fn create(
config: &Config,
maybe_blockchain: Option<&ContractSet>,
user_count: i64,
post_count: i64,
peer_count: i64,
) -> Self {
let mut blockchains = vec![]; let mut blockchains = vec![];
match config.blockchain() { match config.blockchain() {
Some(BlockchainConfig::Ethereum(ethereum_config)) => { Some(BlockchainConfig::Ethereum(ethereum_config)) => {
@ -90,6 +104,11 @@ impl InstanceInfo {
description: config.instance_description.clone(), description: config.instance_description.clone(),
version: get_full_api_version(&config.version), version: get_full_api_version(&config.version),
registrations: config.registrations_open, registrations: config.registrations_open,
stats: InstanceStats {
user_count,
status_count: post_count,
domain_count: peer_count,
},
login_message: config.login_message.clone(), login_message: config.login_message.clone(),
post_character_limit: config.post_character_limit, post_character_limit: config.post_character_limit,
blockchains: blockchains, blockchains: blockchains,

View file

@ -1,18 +1,32 @@
use actix_web::{get, web, HttpResponse, Scope}; use actix_web::{get, web, HttpResponse, Scope};
use crate::config::Config; use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError; use crate::errors::HttpError;
use crate::ethereum::contracts::ContractSet; use crate::ethereum::contracts::ContractSet;
use crate::models::{
instances::queries::get_peer_count,
posts::queries::get_local_post_count,
users::queries::get_user_count,
};
use super::types::InstanceInfo; use super::types::InstanceInfo;
#[get("")] #[get("")]
async fn instance_view( async fn instance_view(
config: web::Data<Config>, config: web::Data<Config>,
db_pool: web::Data<Pool>,
maybe_blockchain: web::Data<Option<ContractSet>>, maybe_blockchain: web::Data<Option<ContractSet>>,
) -> Result<HttpResponse, HttpError> { ) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let user_count = get_user_count(db_client).await?;
let post_count = get_local_post_count(db_client).await?;
let peer_count = get_peer_count(db_client).await?;
let instance = InstanceInfo::create( let instance = InstanceInfo::create(
config.as_ref(), config.as_ref(),
maybe_blockchain.as_ref().as_ref(), maybe_blockchain.as_ref().as_ref(),
user_count,
post_count,
peer_count,
); );
Ok(HttpResponse::Ok().json(instance)) Ok(HttpResponse::Ok().json(instance))
} }

View file

@ -0,0 +1 @@
pub mod queries;

View file

@ -0,0 +1,28 @@
use tokio_postgres::GenericClient;
use crate::errors::DatabaseError;
pub async fn create_instance(
db_client: &impl GenericClient,
hostname: &str,
) -> Result<(), DatabaseError> {
db_client.execute(
"
INSERT INTO instance VALUES ($1)
ON CONFLICT DO NOTHING
",
&[&hostname],
).await?;
Ok(())
}
pub async fn get_peer_count(
db_client: &impl GenericClient,
) -> Result<i64, DatabaseError> {
let row = db_client.query_one(
"SELECT count(instance) FROM instance",
&[],
).await?;
let count = row.try_get("count")?;
Ok(count)
}

View file

@ -1,5 +1,6 @@
pub mod attachments; pub mod attachments;
pub mod cleanup; pub mod cleanup;
pub mod instances;
pub mod invoices; pub mod invoices;
pub mod markers; pub mod markers;
pub mod notifications; pub mod notifications;

View file

@ -10,6 +10,7 @@ use crate::models::cleanup::{
find_orphaned_ipfs_objects, find_orphaned_ipfs_objects,
DeletionQueue, DeletionQueue,
}; };
use crate::models::instances::queries::create_instance;
use crate::models::relationships::types::RelationshipType; use crate::models::relationships::types::RelationshipType;
use crate::utils::currencies::Currency; use crate::utils::currencies::Currency;
use crate::utils::id::new_uuid; use crate::utils::id::new_uuid;
@ -29,13 +30,7 @@ pub async fn create_profile(
) -> Result<DbActorProfile, DatabaseError> { ) -> Result<DbActorProfile, DatabaseError> {
let profile_id = new_uuid(); let profile_id = new_uuid();
if let Some(ref hostname) = profile_data.hostname { if let Some(ref hostname) = profile_data.hostname {
db_client.execute( create_instance(db_client, hostname).await?;
"
INSERT INTO instance VALUES ($1)
ON CONFLICT DO NOTHING
",
&[&hostname],
).await?;
}; };
let row = db_client.query_one( let row = db_client.query_one(
" "