mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 18:41:56 +03:00
Merge pull request #1068 from zed-industries/collab-snapshots
Implement /rpc_server_snapshot endpoint in collab server API
This commit is contained in:
commit
f4d13ef596
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -416,6 +416,25 @@ dependencies = [
|
||||
"mime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-extra"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75330529f6b27544cedc6089108602a056d016df6aa4f2cb24408d840392ef2d"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"bytes",
|
||||
"http",
|
||||
"mime",
|
||||
"pin-project-lite 0.2.9",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.64"
|
||||
@ -593,9 +612,9 @@ checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.0.1"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "cache-padded"
|
||||
@ -841,6 +860,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"async-tungstenite",
|
||||
"axum",
|
||||
"axum-extra",
|
||||
"base64 0.13.0",
|
||||
"clap 3.1.12",
|
||||
"client",
|
||||
@ -4237,12 +4257,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.64"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa 0.4.7",
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -18,6 +18,6 @@ isahc = "1.7"
|
||||
lazy_static = "1.4"
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
smol = "1.2.5"
|
||||
tempdir = "0.3.7"
|
||||
|
@ -21,6 +21,7 @@ anyhow = "1.0.40"
|
||||
async-trait = "0.1.50"
|
||||
async-tungstenite = "0.16"
|
||||
axum = { version = "0.5", features = ["json", "headers", "ws"] }
|
||||
axum-extra = { version = "0.3", features = ["erased-json"] }
|
||||
base64 = "0.13"
|
||||
clap = { version = "3.1", features = ["derive"], optional = true }
|
||||
envy = "0.4.2"
|
||||
@ -70,7 +71,7 @@ ctor = "0.1"
|
||||
env_logger = "0.8"
|
||||
util = { path = "../util" }
|
||||
lazy_static = "1.4"
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
|
||||
[features]
|
||||
seed-support = ["clap", "lipsum", "reqwest"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
auth,
|
||||
db::{User, UserId},
|
||||
rpc::ResultExt,
|
||||
rpc::{self, ResultExt},
|
||||
AppState, Error, Result,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
@ -14,12 +14,13 @@ use axum::{
|
||||
routing::{get, post, put},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use axum_extra::response::ErasedJson;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tower::ServiceBuilder;
|
||||
use tracing::instrument;
|
||||
|
||||
pub fn routes(rpc_server: &Arc<crate::rpc::Server>, state: Arc<AppState>) -> Router<Body> {
|
||||
pub fn routes(rpc_server: &Arc<rpc::Server>, state: Arc<AppState>) -> Router<Body> {
|
||||
Router::new()
|
||||
.route("/users", get(get_users).post(create_user))
|
||||
.route(
|
||||
@ -29,6 +30,7 @@ pub fn routes(rpc_server: &Arc<crate::rpc::Server>, state: Arc<AppState>) -> Rou
|
||||
.route("/users/:id/access_tokens", post(create_access_token))
|
||||
.route("/invite_codes/:code", get(get_user_for_invite_code))
|
||||
.route("/panic", post(trace_panic))
|
||||
.route("/rpc_server_snapshot", get(get_rpc_server_snapshot))
|
||||
.layer(
|
||||
ServiceBuilder::new()
|
||||
.layer(Extension(state))
|
||||
@ -84,7 +86,7 @@ struct CreateUserParams {
|
||||
async fn create_user(
|
||||
Json(params): Json<CreateUserParams>,
|
||||
Extension(app): Extension<Arc<AppState>>,
|
||||
Extension(rpc_server): Extension<Arc<crate::rpc::Server>>,
|
||||
Extension(rpc_server): Extension<Arc<rpc::Server>>,
|
||||
) -> Result<Json<User>> {
|
||||
println!("{:?}", params);
|
||||
|
||||
@ -177,6 +179,12 @@ async fn trace_panic(panic: Json<Panic>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_rpc_server_snapshot(
|
||||
Extension(rpc_server): Extension<Arc<rpc::Server>>,
|
||||
) -> Result<ErasedJson> {
|
||||
Ok(ErasedJson::pretty(rpc_server.snapshot().await))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CreateAccessTokenQueryParams {
|
||||
public_key: String,
|
||||
|
@ -104,6 +104,12 @@ impl From<hyper::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
fn from(error: serde_json::Error) -> Self {
|
||||
Self::Internal(error.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for Error {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
|
@ -33,6 +33,7 @@ use rpc::{
|
||||
proto::{self, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, RequestMessage},
|
||||
Connection, ConnectionId, Peer, Receipt, TypedEnvelope,
|
||||
};
|
||||
use serde::{Serialize, Serializer};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
future::Future,
|
||||
@ -85,6 +86,7 @@ pub struct Server {
|
||||
notifications: Option<mpsc::UnboundedSender<()>>,
|
||||
}
|
||||
|
||||
|
||||
pub trait Executor: Send + Clone {
|
||||
type Sleep: Send + Future;
|
||||
fn spawn_detached<F: 'static + Send + Future<Output = ()>>(&self, future: F);
|
||||
@ -107,6 +109,23 @@ struct StoreWriteGuard<'a> {
|
||||
_not_send: PhantomData<Rc<()>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct ServerSnapshot<'a> {
|
||||
peer: &'a Peer,
|
||||
#[serde(serialize_with = "serialize_deref")]
|
||||
store: RwLockReadGuard<'a, Store>,
|
||||
}
|
||||
|
||||
pub fn serialize_deref<S, T, U>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
T: Deref<Target = U>,
|
||||
U: Serialize
|
||||
{
|
||||
Serialize::serialize(value.deref(), serializer)
|
||||
}
|
||||
|
||||
|
||||
impl Server {
|
||||
pub fn new(
|
||||
app_state: Arc<AppState>,
|
||||
@ -1469,6 +1488,13 @@ impl Server {
|
||||
_not_send: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn snapshot<'a>(self: &'a Arc<Self>) -> ServerSnapshot<'a> {
|
||||
ServerSnapshot {
|
||||
store: self.store.read().await,
|
||||
peer: &self.peer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for StoreReadGuard<'a> {
|
||||
|
@ -2,18 +2,21 @@ use crate::db::{self, ChannelId, UserId};
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::{hash_map::Entry, BTreeMap, HashMap, HashSet};
|
||||
use rpc::{proto, ConnectionId, Receipt};
|
||||
use serde::Serialize;
|
||||
use std::{collections::hash_map, mem, path::PathBuf};
|
||||
use tracing::instrument;
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Serialize)]
|
||||
pub struct Store {
|
||||
connections: HashMap<ConnectionId, ConnectionState>,
|
||||
connections_by_user_id: HashMap<UserId, HashSet<ConnectionId>>,
|
||||
projects: HashMap<u64, Project>,
|
||||
#[serde(skip)]
|
||||
channels: HashMap<ChannelId, Channel>,
|
||||
next_project_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ConnectionState {
|
||||
user_id: UserId,
|
||||
projects: HashSet<u64>,
|
||||
@ -21,21 +24,25 @@ struct ConnectionState {
|
||||
channels: HashSet<ChannelId>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Project {
|
||||
pub host_connection_id: ConnectionId,
|
||||
pub host_user_id: UserId,
|
||||
pub guests: HashMap<ConnectionId, (ReplicaId, UserId)>,
|
||||
#[serde(skip)]
|
||||
pub join_requests: HashMap<UserId, Vec<Receipt<proto::JoinProject>>>,
|
||||
pub active_replica_ids: HashSet<ReplicaId>,
|
||||
pub worktrees: HashMap<u64, Worktree>,
|
||||
pub language_servers: Vec<proto::LanguageServer>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Serialize)]
|
||||
pub struct Worktree {
|
||||
pub root_name: String,
|
||||
pub visible: bool,
|
||||
#[serde(skip)]
|
||||
pub entries: HashMap<u64, proto::Entry>,
|
||||
#[serde(skip)]
|
||||
pub diagnostic_summaries: BTreeMap<PathBuf, proto::DiagnosticSummary>,
|
||||
pub scan_id: u64,
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ workspace = { path = "../workspace" }
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
editor = { path = "../editor", features = ["test-support"] }
|
||||
project = { path = "../project", features = ["test-support"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
ctor = "0.1"
|
||||
env_logger = "0.8"
|
||||
|
@ -21,7 +21,7 @@ postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
|
||||
[dev-dependencies]
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
ctor = "0.1"
|
||||
env_logger = "0.8"
|
||||
|
@ -37,7 +37,7 @@ rand = "0.8.3"
|
||||
resvg = "0.14"
|
||||
seahash = "4.1"
|
||||
serde = { version = "1.0.125", features = ["derive"] }
|
||||
serde_json = "1.0.64"
|
||||
serde_json = "1.0"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "1.2"
|
||||
time = { version = "0.3" }
|
||||
|
@ -17,7 +17,7 @@ workspace = { path = "../workspace" }
|
||||
|
||||
[dev-dependencies]
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
ctor = "0.1"
|
||||
env_logger = "0.8"
|
||||
|
@ -41,7 +41,7 @@ postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
rand = "0.8.3"
|
||||
regex = "1.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
sha2 = "0.10"
|
||||
similar = "1.3"
|
||||
smol = "1.2.5"
|
||||
|
@ -23,4 +23,4 @@ unicase = "2.6"
|
||||
editor = { path = "../editor", features = ["test-support"] }
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
|
@ -10,6 +10,7 @@ use futures::{
|
||||
FutureExt, SinkExt, StreamExt,
|
||||
};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use serde::{ser::SerializeStruct, Serialize};
|
||||
use smol_timeout::TimeoutExt;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::{
|
||||
@ -24,7 +25,7 @@ use std::{
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize)]
|
||||
pub struct ConnectionId(pub u32);
|
||||
|
||||
impl fmt::Display for ConnectionId {
|
||||
@ -89,10 +90,12 @@ pub struct Peer {
|
||||
next_connection_id: AtomicU32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Serialize)]
|
||||
pub struct ConnectionState {
|
||||
#[serde(skip)]
|
||||
outgoing_tx: mpsc::UnboundedSender<proto::Message>,
|
||||
next_message_id: Arc<AtomicU32>,
|
||||
#[serde(skip)]
|
||||
response_channels:
|
||||
Arc<Mutex<Option<HashMap<u32, oneshot::Sender<(proto::Envelope, oneshot::Sender<()>)>>>>>,
|
||||
}
|
||||
@ -471,6 +474,17 @@ impl Peer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Peer {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("Peer", 2)?;
|
||||
state.serialize_field("connections", &*self.connections.read())?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -26,6 +26,6 @@ smallvec = { version = "1.6", features = ["union"] }
|
||||
[dev-dependencies]
|
||||
editor = { path = "../editor", features = ["test-support"] }
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
unindent = "0.1"
|
||||
|
@ -20,6 +20,6 @@ anyhow = "1.0.38"
|
||||
json_comments = "0.2"
|
||||
schemars = "0.8"
|
||||
serde = { version = "1", features = ["derive", "rc"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_path_to_error = "0.1.4"
|
||||
toml = "0.5"
|
||||
|
@ -13,6 +13,6 @@ anyhow = "1.0.38"
|
||||
indexmap = "1.6.2"
|
||||
parking_lot = "0.11.1"
|
||||
serde = { version = "1", features = ["derive", "rc"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_path_to_error = "0.1.4"
|
||||
toml = "0.5"
|
||||
|
@ -15,6 +15,6 @@ futures = "0.3"
|
||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
rand = { version = "0.8", optional = true }
|
||||
tempdir = { version = "0.3.7", optional = true }
|
||||
serde_json = { version = "1.0.64", features = [
|
||||
serde_json = { version = "1.0", features = [
|
||||
"preserve_order",
|
||||
], optional = true }
|
||||
|
@ -26,7 +26,7 @@ log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
parking_lot = "0.11.1"
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
serde = { version = "1", features = ["derive", "rc"] }
|
||||
serde_json = { version = "1", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -76,7 +76,7 @@ regex = "1.5"
|
||||
rsa = "0.4"
|
||||
rust-embed = { version = "6.3", features = ["include-exclude"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_path_to_error = "0.1.4"
|
||||
simplelog = "0.9"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
@ -107,7 +107,7 @@ settings = { path = "../settings", features = ["test-support"] }
|
||||
util = { path = "../util", features = ["test-support"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
env_logger = "0.8"
|
||||
serde_json = { version = "1.0.64", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
unindent = "0.1.7"
|
||||
|
||||
[package.metadata.bundle]
|
||||
|
@ -8,7 +8,6 @@ export function workspaceBackground(theme: Theme) {
|
||||
}
|
||||
|
||||
export default function workspace(theme: Theme) {
|
||||
|
||||
const tab = {
|
||||
height: 32,
|
||||
background: workspaceBackground(theme),
|
||||
|
Loading…
Reference in New Issue
Block a user