JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Giterated Stack `ObjectValue` and `Setting` refactor.

This refactor adds value and setting update events, as well as value getters. Additionally, the stack is now the owner of the ability to write settings into storage. This is accomplished with the `MetadataProvider` trait. This sets up the ground work for push federation, cache, and basically everything else. commit 7befc583cb3e0c6719506c550ed66ac76293413c Author: Amber <[email protected]> Date: Fri Sep 29 15:46:48 2023 -0500 Finish value and settings refactor in the stack. commit 3ac09994a0caafd1a0b95d9a781c7f202f20e75b Author: Amber <[email protected]> Date: Fri Sep 29 09:46:32 2023 -0500 Add set_setting handling back in commit 84fd31e3eae85d98fa68a28b333dbb32cde3bdb8 Author: Amber <[email protected]> Date: Wed Sep 27 06:36:31 2023 -0500 Remove some allocations from meta types commit 16c310ce3680c4a14ed35083b6a230aaecd43152 Author: Amber <[email protected]> Date: Wed Sep 27 05:35:03 2023 -0500 Add cargo metadata commit eb2520a20001bac7b21c6c3d34f62db32f0ada80 Author: Amber <[email protected]> Date: Wed Sep 27 05:26:27 2023 -0500 Refactor setting and value management to use the unified stack. Allows for tight management, inspection, and eventing of setting and value management. commit 901fe103da0fce4b40f33b0a8b64404049ae03cf Author: Amber <[email protected]> Date: Wed Sep 27 02:38:33 2023 -0500 Set up ground work for value / settings refactor

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨c377e4d

⁨giterated-daemon/src/main.rs⁩ - ⁨6495⁩ bytes
Raw
1 use anyhow::Error;
2 use connection::{Connections, RawConnection};
3 use giterated_daemon::{
4 authentication::AuthenticationTokenGranter,
5 backend::{
6 git::GitBackend, settings::DatabaseSettings, user::UserAuth, RepositoryBackend, UserBackend,
7 },
8 connection::{self, wrapper::connection_wrapper},
9 database_backend::DatabaseBackend,
10 federation::connections::InstanceConnections,
11 };
12
13 use giterated_models::instance::Instance;
14
15 use giterated_stack::{GiteratedStack, StackOperationState};
16 use sqlx::{postgres::PgConnectOptions, ConnectOptions, PgPool};
17 use std::{net::SocketAddr, str::FromStr, sync::Arc};
18 use tokio::{
19 fs::File,
20 io::{AsyncRead, AsyncReadExt, AsyncWrite},
21 net::{TcpListener, TcpStream},
22 sync::{Mutex, OnceCell},
23 };
24 use tokio_tungstenite::{accept_async, WebSocketStream};
25 use tokio_util::task::LocalPoolHandle;
26 use toml::Table;
27
28 #[macro_use]
29 extern crate tracing;
30
31 #[tokio::main]
32 async fn main() -> Result<(), Error> {
33 tracing_subscriber::fmt::init();
34 let config: Table = {
35 let mut file = File::open("Giterated.toml").await?;
36 let mut text = String::new();
37 file.read_to_string(&mut text).await?;
38 text.parse()?
39 };
40 let mut listener = TcpListener::bind(config["giterated"]["bind"].as_str().unwrap()).await?;
41 let connections: Arc<Mutex<Connections>> = Arc::default();
42 let instance_connections: Arc<Mutex<InstanceConnections>> = Arc::default();
43 let db_conn_options = PgConnectOptions::new()
44 .host(config["postgres"]["host"].as_str().unwrap())
45 .port(config["postgres"]["port"].as_integer().unwrap() as u16)
46 .database(config["postgres"]["database"].as_str().unwrap())
47 .username(config["postgres"]["user"].as_str().unwrap())
48 .password(config["postgres"]["password"].as_str().unwrap())
49 .log_statements(log::LevelFilter::Off);
50 let db_pool = PgPool::connect_with(db_conn_options).await?;
51
52 debug!("Running database migrations...");
53 sqlx::migrate!().run(&db_pool).await?;
54 info!("Connected");
55
56 let stack_cell = Arc::new(OnceCell::default());
57
58 let settings = Arc::new(Mutex::new(DatabaseSettings {
59 pg_pool: db_pool.clone(),
60 stack: stack_cell.clone(),
61 }));
62
63 let repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>> =
64 Arc::new(Mutex::new(GitBackend {
65 pg_pool: db_pool.clone(),
66 repository_folder: String::from(
67 config["giterated"]["backend"]["git"]["root"]
68 .as_str()
69 .unwrap(),
70 ),
71 instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap())
72 .unwrap(),
73 stack: stack_cell.clone(),
74 }));
75
76 let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter {
77 config: config.clone(),
78 instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
79 }));
80
81 let user_backend: Arc<Mutex<dyn UserBackend + Send>> = Arc::new(Mutex::new(UserAuth::new(
82 db_pool.clone(),
83 &Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
84 token_granter.clone(),
85 settings.clone(),
86 )));
87
88 info!("Connected");
89
90 let database_backend = DatabaseBackend::new(
91 Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
92 user_backend.clone(),
93 repository_backend.clone(),
94 db_pool.clone(),
95 stack_cell.clone(),
96 );
97
98 let mut runtime = GiteratedStack::default();
99
100 let database_backend = database_backend.into_substack();
101 runtime.merge_builder(database_backend);
102
103 let runtime = Arc::new(runtime);
104
105 stack_cell
106 .set(runtime.clone())
107 .expect("failed to store global daemon stack");
108
109 let operation_state = {
110 StackOperationState {
111 our_instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap())
112 .unwrap(),
113 runtime: runtime.clone(),
114 instance: None,
115 user: None,
116 }
117 };
118
119 let pool = LocalPoolHandle::new(5);
120
121 loop {
122 let stream = accept_stream(&mut listener).await;
123 info!("Connected");
124
125 let (stream, address) = match stream {
126 Ok(stream) => stream,
127 Err(err) => {
128 error!("Failed to accept connection. {:?}", err);
129 continue;
130 }
131 };
132
133 info!("Accepted connection from {}", address);
134
135 let connection = accept_websocket_connection(stream).await;
136
137 let connection = match connection {
138 Ok(connection) => connection,
139 Err(err) => {
140 error!(
141 "Failed to initiate Websocket connection from {}. {:?}",
142 address, err
143 );
144 continue;
145 }
146 };
147
148 info!("Websocket connection established with {}", address);
149 let connections_cloned = connections.clone();
150 let repository_backend = repository_backend.clone();
151 let user_backend = user_backend.clone();
152 let token_granter = token_granter.clone();
153 let settings = settings.clone();
154 let instance_connections = instance_connections.clone();
155 let config = config.clone();
156 let runtime = runtime.clone();
157 let operation_state = operation_state.clone();
158
159 pool.spawn_pinned(move || {
160 connection_wrapper(
161 connection,
162 connections_cloned,
163 repository_backend,
164 user_backend,
165 token_granter,
166 settings,
167 address,
168 Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
169 instance_connections,
170 config,
171 runtime,
172 operation_state,
173 )
174 });
175
176 let connection = RawConnection {
177 task: tokio::spawn(async move { () }),
178 };
179
180 connections.lock().await.connections.push(connection);
181 }
182 }
183
184 async fn accept_stream(listener: &mut TcpListener) -> Result<(TcpStream, SocketAddr), Error> {
185 let stream = listener.accept().await?;
186
187 Ok(stream)
188 }
189
190 async fn accept_websocket_connection<S: AsyncRead + AsyncWrite + Unpin>(
191 stream: S,
192 ) -> Result<WebSocketStream<S>, Error> {
193 let connection = accept_async(stream).await?;
194
195 Ok(connection)
196 }
197