first pass of merging in warp (doesn't build)
This commit is contained in:
@@ -14,45 +14,36 @@
|
||||
//! that hit one of these panics have likely wired a non-preferences
|
||||
//! code path through the fake by mistake.
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_channel::Sender;
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use cloud_object_client::ObjectPermissionUpdateResult;
|
||||
use galaxy_graphql::object_permissions::AccessLevel;
|
||||
|
||||
use crate::{
|
||||
cloud_object::{
|
||||
model::{
|
||||
actions::{ObjectActionHistory, ObjectActionType},
|
||||
generic_string_model::GenericStringObjectId,
|
||||
},
|
||||
BulkCreateCloudObjectResult, BulkCreateGenericStringObjectsRequest,
|
||||
CreateCloudObjectResult, CreateObjectRequest, CreatedCloudObject,
|
||||
GenericStringObjectFormat, GenericStringObjectUniqueKey, JsonObjectType,
|
||||
ObjectDeleteResult, ObjectIdType, ObjectMetadataUpdateResult, ObjectPermissionUpdateResult,
|
||||
ObjectPermissionsUpdateData, ObjectType, ObjectsToUpdate, Owner, Revision,
|
||||
RevisionAndLastEditor, ServerFolder, ServerMetadata, ServerNotebook, ServerObject,
|
||||
ServerPermissions, ServerPreference, ServerWorkflow, UpdateCloudObjectResult,
|
||||
},
|
||||
drive::{folders::FolderId, sharing::SharingAccessLevel},
|
||||
notebooks::NotebookId,
|
||||
server::{
|
||||
cloud_objects::{
|
||||
listener::ObjectUpdateMessage,
|
||||
update_manager::{GetCloudObjectResponse, InitialLoadResponse},
|
||||
},
|
||||
ids::{ServerId, ServerIdAndType, SyncId},
|
||||
server_api::object::{GuestIdentifier, ObjectClient},
|
||||
sync_queue::SerializedModel,
|
||||
},
|
||||
settings::cloud_preferences::{CloudPreferenceModel, Platform, Preference},
|
||||
workflows::WorkflowId,
|
||||
use crate::cloud_object::model::actions::{ObjectActionHistory, ObjectActionType};
|
||||
use crate::cloud_object::model::generic_string_model::GenericStringObjectId;
|
||||
use crate::cloud_object::{
|
||||
BulkCreateCloudObjectResult, BulkCreateGenericStringObjectsRequest, CreateCloudObjectResult,
|
||||
CreateObjectRequest, CreatedCloudObject, GenericStringObjectFormat,
|
||||
GenericStringObjectUniqueKey, JsonObjectType, ObjectDeleteResult, ObjectIdType,
|
||||
ObjectMetadataUpdateResult, ObjectPermissionsUpdateData, ObjectType, ObjectsToUpdate, Owner,
|
||||
Revision, RevisionAndLastEditor, ServerFolder, ServerMetadata, ServerNotebook, ServerObject,
|
||||
ServerPermissions, ServerPreference, ServerWorkflow, UpdateCloudObjectResult,
|
||||
};
|
||||
use crate::drive::folders::FolderId;
|
||||
use crate::drive::sharing::SharingAccessLevel;
|
||||
use crate::notebooks::NotebookId;
|
||||
use crate::server::cloud_objects::listener::ObjectUpdateMessage;
|
||||
use crate::server::cloud_objects::update_manager::{GetCloudObjectResponse, InitialLoadResponse};
|
||||
use crate::server::ids::{ServerId, ServerIdAndType, SyncId};
|
||||
use crate::server::server_api::object::{GuestIdentifier, ObjectClient};
|
||||
use crate::server::sync_queue::SerializedModel;
|
||||
use crate::settings::cloud_preferences::{CloudPreferenceModel, Platform, Preference};
|
||||
use crate::workflows::WorkflowId;
|
||||
|
||||
/// A stateful fake cloud preferences backend.
|
||||
#[derive(Clone, Default)]
|
||||
@@ -153,12 +144,12 @@ impl FakeObjectClient {
|
||||
anyone_link_sharing: None,
|
||||
permissions_last_updated_ts: stored.metadata_ts.into(),
|
||||
};
|
||||
let server_pref = ServerPreference {
|
||||
id: SyncId::ServerId(ServerId::from(*id)),
|
||||
model: stored.model.clone(),
|
||||
let server_pref = ServerPreference::new(
|
||||
SyncId::ServerId(ServerId::from(*id)),
|
||||
stored.model.clone(),
|
||||
metadata,
|
||||
permissions,
|
||||
};
|
||||
);
|
||||
Box::new(server_pref) as Box<dyn ServerObject>
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1,35 +1,21 @@
|
||||
use crate::network::{NetworkStatus, NetworkStatusEvent, NetworkStatusKind};
|
||||
use crate::report_error;
|
||||
use crate::server::{ids::ServerId, retry_strategies::LISTENER_RETRY_STRATEGY};
|
||||
use crate::system::{SystemStats, SystemStatsEvent};
|
||||
use crate::workspaces::{
|
||||
user_profiles::UserProfileWithUID,
|
||||
user_workspaces::{UserWorkspaces, UserWorkspacesEvent},
|
||||
};
|
||||
use crate::{
|
||||
cloud_object::{
|
||||
model::{
|
||||
actions::ObjectActionHistory,
|
||||
persistence::{CloudModel, CloudModelEvent},
|
||||
},
|
||||
ServerCloudObject, ServerMetadata, ServerPermissions,
|
||||
},
|
||||
server::server_api::object::ObjectClient,
|
||||
};
|
||||
|
||||
use super::update_manager::UpdateManager;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use futures_util::stream::AbortHandle;
|
||||
use galaxyui::r#async::Timer;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_channel::Sender;
|
||||
|
||||
use galaxyui::{Entity, ModelContext, RequestState, SingletonEntity};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use cloud_object_client::ObjectUpdateMessage;
|
||||
use futures_util::stream::AbortHandle;
|
||||
use instant::Instant;
|
||||
use warpui::r#async::Timer;
|
||||
use warpui::{Entity, ModelContext, ModelHandle, RequestState, SingletonEntity};
|
||||
|
||||
use super::update_manager::UpdateManager;
|
||||
use crate::cloud_object::model::persistence::{CloudModel, CloudModelEvent};
|
||||
use crate::network::{NetworkStatus, NetworkStatusEvent, NetworkStatusKind};
|
||||
use crate::report_error;
|
||||
use crate::server::retry_strategies::LISTENER_RETRY_STRATEGY;
|
||||
use crate::server::server_api::object::ObjectClient;
|
||||
use crate::system::{SystemStats, SystemStatsEvent};
|
||||
use crate::workspaces::user_workspaces::{UserWorkspaces, UserWorkspacesEvent};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
/// Between successful websocket connections, we ensured at least this amount of time
|
||||
@@ -86,52 +72,6 @@ pub struct Listener {
|
||||
pending_refresh_abort_handle: Option<AbortHandle>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum ObjectUpdateMessage {
|
||||
ObjectMetadataChanged {
|
||||
metadata: ServerMetadata,
|
||||
},
|
||||
ObjectPermissionsChanged,
|
||||
// TODO(CLD-2425): Replace `ObjectPermissionsChanged` with this.
|
||||
ObjectPermissionsChangedV2 {
|
||||
object_uid: ServerId,
|
||||
permissions: ServerPermissions,
|
||||
user_profiles: Vec<UserProfileWithUID>,
|
||||
},
|
||||
ObjectContentChanged {
|
||||
server_object: Box<ServerCloudObject>,
|
||||
last_editor: Option<UserProfileWithUID>,
|
||||
},
|
||||
ObjectDeleted {
|
||||
object_uid: ServerId,
|
||||
},
|
||||
ObjectActionOccurred {
|
||||
history: ObjectActionHistory,
|
||||
},
|
||||
TeamMembershipsChanged,
|
||||
AmbientTaskUpdated {
|
||||
task_id: String,
|
||||
timestamp: DateTime<Utc>,
|
||||
},
|
||||
}
|
||||
|
||||
impl ObjectUpdateMessage {
|
||||
fn as_str(&self) -> &'static str {
|
||||
use ObjectUpdateMessage::*;
|
||||
match self {
|
||||
ObjectMetadataChanged { .. } => "ObjectMetadataChanged",
|
||||
ObjectPermissionsChanged => "ObjectPermissionsChanged",
|
||||
ObjectPermissionsChangedV2 { .. } => "ObjectPermissionsChanged (V2)",
|
||||
ObjectContentChanged { .. } => "ObjectContentChanged",
|
||||
ObjectDeleted { .. } => "ObjectDeleted",
|
||||
ObjectActionOccurred { .. } => "ObjectActionOccurred",
|
||||
TeamMembershipsChanged => "TeamMembershipsChanged",
|
||||
AmbientTaskUpdated { .. } => "AmbientTaskUpdated",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Listener {
|
||||
pub fn new(cloud_objects_client: Arc<dyn ObjectClient>, ctx: &mut ModelContext<Self>) -> Self {
|
||||
let (subscription_ready_tx, subscription_ready_rx) = async_channel::unbounded();
|
||||
@@ -197,6 +137,7 @@ impl Listener {
|
||||
// If the user is part of a team, we should start subscribing for updates.
|
||||
fn handle_user_workspaces_event(
|
||||
&mut self,
|
||||
_: ModelHandle<UserWorkspaces>,
|
||||
event: &UserWorkspacesEvent,
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) {
|
||||
@@ -214,7 +155,12 @@ impl Listener {
|
||||
}
|
||||
|
||||
// If the user has access to >= 1 cloud objects, we should subscribe for updates.
|
||||
fn handle_cloud_model_event(&mut self, _event: &CloudModelEvent, ctx: &mut ModelContext<Self>) {
|
||||
fn handle_cloud_model_event(
|
||||
&mut self,
|
||||
_: ModelHandle<CloudModel>,
|
||||
_event: &CloudModelEvent,
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) {
|
||||
if self.has_non_welcome_cloud_objects(ctx) {
|
||||
self.start_listener(ctx);
|
||||
}
|
||||
@@ -225,7 +171,12 @@ impl Listener {
|
||||
// To get around this, we manually abort the future (effectively closing the websocket)
|
||||
// when the CPU goes to sleep and restart it when it's awakened.
|
||||
// https://linear.app/warpdotdev/issue/CLD-172/websocket-hangs-when-closed-during-cpu-sleep
|
||||
fn handle_cpu_event(&mut self, event: &SystemStatsEvent, ctx: &mut ModelContext<Self>) {
|
||||
fn handle_cpu_event(
|
||||
&mut self,
|
||||
_: ModelHandle<SystemStats>,
|
||||
event: &SystemStatsEvent,
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
SystemStatsEvent::CpuWasAwakened => {
|
||||
if let Some(abort_handle) = self.current_subscription_abort_handle.take() {
|
||||
@@ -252,6 +203,7 @@ impl Listener {
|
||||
|
||||
fn handle_network_status_changed_event(
|
||||
&mut self,
|
||||
_: ModelHandle<NetworkStatus>,
|
||||
event: &NetworkStatusEvent,
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) {
|
||||
|
||||
@@ -1,39 +1,25 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{
|
||||
mpsc::{sync_channel, Receiver},
|
||||
Arc,
|
||||
},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::{sync_channel, Receiver};
|
||||
use std::sync::Arc;
|
||||
|
||||
use galaxy_core::execution_mode::{AppExecutionMode, ExecutionMode};
|
||||
use galaxyui::{App, ModelHandle, SingletonEntity};
|
||||
use cloud_object_client::{MockObjectClient, ObjectClient};
|
||||
use settings::manager::SettingsManager;
|
||||
|
||||
use crate::{
|
||||
auth::{auth_manager::AuthManager, AuthStateProvider},
|
||||
cloud_object::model::{
|
||||
actions::ObjectActions,
|
||||
persistence::{CloudModel, CloudModelEvent},
|
||||
},
|
||||
network::NetworkStatus,
|
||||
persistence::ModelEvent,
|
||||
server::{
|
||||
server_api::{
|
||||
object::{MockObjectClient, ObjectClient},
|
||||
ServerApiProvider,
|
||||
},
|
||||
sync_queue::SyncQueue,
|
||||
telemetry::context_provider::AppTelemetryContextProvider,
|
||||
},
|
||||
settings::{PrivacySettings, WarpDrivePrivacySettings},
|
||||
workspaces::{
|
||||
team_tester::TeamTesterStatus, update_manager::TeamUpdateManager,
|
||||
user_profiles::UserProfiles, user_workspaces::UserWorkspaces,
|
||||
},
|
||||
};
|
||||
|
||||
use super::update_manager::UpdateManager;
|
||||
use crate::auth::auth_manager::AuthManager;
|
||||
use crate::auth::AuthStateProvider;
|
||||
use crate::cloud_object::model::actions::ObjectActions;
|
||||
use crate::cloud_object::model::persistence::{CloudModel, CloudModelEvent};
|
||||
use crate::network::NetworkStatus;
|
||||
use crate::persistence::ModelEvent;
|
||||
use crate::server::server_api::ServerApiProvider;
|
||||
use crate::server::sync_queue::SyncQueue;
|
||||
use crate::server::telemetry::context_provider::AppTelemetryContextProvider;
|
||||
use crate::settings::{PrivacySettings, WarpDrivePrivacySettings};
|
||||
use crate::workspaces::team_tester::TeamTesterStatus;
|
||||
use crate::workspaces::update_manager::TeamUpdateManager;
|
||||
use crate::workspaces::user_profiles::UserProfiles;
|
||||
use crate::workspaces::user_workspaces::UserWorkspaces;
|
||||
|
||||
/// The size of the bounded channel that we use to queue persistence/sqlite-related events.
|
||||
const CHANNEL_SIZE: usize = 128;
|
||||
|
||||
@@ -1,75 +1,13 @@
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use crate::ai::mcp::templatable::{CloudTemplatableMCPServerModel, TemplatableMCPServer};
|
||||
use crate::{
|
||||
ai::{
|
||||
agent::conversation::AIConversationId,
|
||||
ambient_agents::scheduled::{CloudScheduledAmbientAgentModel, ScheduledAmbientAgent},
|
||||
blocklist::BlocklistAIHistoryModel,
|
||||
cloud_environments::{AmbientAgentEnvironment, CloudAmbientAgentEnvironmentModel},
|
||||
execution_profiles::{
|
||||
profiles::AIExecutionProfilesModel, AIExecutionProfile, CloudAIExecutionProfileModel,
|
||||
},
|
||||
facts::{AIFact, CloudAIFactModel},
|
||||
},
|
||||
auth::{auth_manager::AuthManager, AuthStateProvider},
|
||||
cloud_object::{
|
||||
model::{
|
||||
actions::{ObjectAction, ObjectActionHistory, ObjectActionType, ObjectActions},
|
||||
generic_string_model::{
|
||||
GenericStringModel, GenericStringObjectId, Serializer, StringModel,
|
||||
},
|
||||
persistence::{CloudModel, CloudModelEvent, UpdateSource},
|
||||
view::{CloudViewModel, Editor, EditorState},
|
||||
},
|
||||
CloudLinkSharing, CloudModelType, CloudObject, CloudObjectEventEntrypoint,
|
||||
CloudObjectLocation, CloudObjectSyncStatus, CreateCloudObjectResult, CreateObjectRequest,
|
||||
GenericCloudObject, GenericServerObject, GenericStringObjectFormat, JsonObjectType,
|
||||
NumInFlightRequests, ObjectDeleteResult, ObjectIdType, ObjectMetadataUpdateResult,
|
||||
ObjectPermissionsUpdateData, ObjectType, Owner, Revision, RevisionAndLastEditor,
|
||||
ServerAIExecutionProfile, ServerAIFact, ServerAmbientAgentEnvironment,
|
||||
ServerCloudAgentConfig, ServerCloudObject, ServerEnvVarCollection, ServerFolder,
|
||||
ServerMCPServer, ServerMetadata, ServerNotebook, ServerObject, ServerPermissions,
|
||||
ServerPreference, ServerScheduledAmbientAgent, ServerTemplatableMCPServer, ServerWorkflow,
|
||||
ServerWorkflowEnum, Space, UpdateCloudObjectResult,
|
||||
},
|
||||
drive::{
|
||||
folders::{CloudFolderModel, FolderId},
|
||||
sharing::SharingAccessLevel,
|
||||
CloudObjectTypeAndId,
|
||||
},
|
||||
env_vars::{CloudEnvVarCollectionModel, EnvVarCollection},
|
||||
network::{NetworkStatus, NetworkStatusEvent, NetworkStatusKind},
|
||||
notebooks::{CloudNotebookModel, NotebookId},
|
||||
persistence::ModelEvent,
|
||||
server::{
|
||||
ids::{
|
||||
parse_sqlite_id_to_uid, ClientId, HashableId, HashedSqliteId, ObjectUid, ServerId,
|
||||
SyncId, ToServerId,
|
||||
},
|
||||
retry_strategies::{
|
||||
OUT_OF_BAND_REQUEST_RETRY_STRATEGY, PERIODIC_POLL, PERIODIC_POLL_RETRY_STRATEGY,
|
||||
},
|
||||
server_api::object::{GuestIdentifier, ObjectClient},
|
||||
sync_queue::{
|
||||
CreationFailureReason, GenericStringObjectToCreate, QueueItem, SyncQueue,
|
||||
SyncQueueEvent,
|
||||
},
|
||||
},
|
||||
settings::cloud_preferences::Preference,
|
||||
util::sync::Condition,
|
||||
workflows::{
|
||||
workflow::Workflow,
|
||||
workflow_enum::{CloudWorkflowEnum, CloudWorkflowEnumModel, WorkflowEnum},
|
||||
CloudWorkflowModel, WorkflowId,
|
||||
},
|
||||
workspaces::{
|
||||
team_tester::{TeamTesterStatus, TeamTesterStatusEvent},
|
||||
update_manager::TeamUpdateManager,
|
||||
user_profiles::{UserProfileWithUID, UserProfiles},
|
||||
user_workspaces::UserWorkspaces,
|
||||
},
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::future::Future;
|
||||
use std::sync::mpsc::SyncSender;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(test)]
|
||||
pub use cloud_object_client::GetCloudObjectResponse;
|
||||
pub use cloud_object_client::InitialLoadResponse;
|
||||
use futures::channel::oneshot::{self, Receiver};
|
||||
use futures::stream::AbortHandle;
|
||||
use galaxy_core::features::FeatureFlag;
|
||||
@@ -82,12 +20,78 @@ use galaxyui::{Entity, ModelContext, RequestState, RetryOption, SingletonEntity}
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::future::Future;
|
||||
use std::sync::{mpsc::SyncSender, Arc};
|
||||
use std::time::Duration;
|
||||
use galaxy_core::report_error;
|
||||
use galaxy_util::sync::Condition;
|
||||
use galaxyui::{
|
||||
duration_with_jitter, AppContext, Entity, ModelContext, ModelHandle, RequestState, RetryOption,
|
||||
SingletonEntity,
|
||||
};
|
||||
|
||||
use super::listener::ObjectUpdateMessage;
|
||||
use crate::ai::agent::conversation::AIConversationId;
|
||||
use crate::ai::ambient_agents::scheduled::{
|
||||
CloudScheduledAmbientAgentModel, ScheduledAmbientAgent,
|
||||
};
|
||||
use crate::ai::ambient_agents::AmbientAgentTaskId;
|
||||
use crate::ai::blocklist::BlocklistAIHistoryModel;
|
||||
use crate::ai::cloud_environments::{AmbientAgentEnvironment, CloudAmbientAgentEnvironmentModel};
|
||||
use crate::ai::execution_profiles::profiles::AIExecutionProfilesModel;
|
||||
use crate::ai::execution_profiles::{AIExecutionProfile, CloudAIExecutionProfileModel};
|
||||
use crate::ai::facts::{AIFact, CloudAIFactModel};
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use crate::ai::mcp::templatable::{CloudTemplatableMCPServerModel, TemplatableMCPServer};
|
||||
use crate::auth::auth_manager::AuthManager;
|
||||
use crate::auth::AuthStateProvider;
|
||||
use crate::cloud_object::model::actions::{
|
||||
ObjectAction, ObjectActionHistory, ObjectActionType, ObjectActions,
|
||||
};
|
||||
use crate::cloud_object::model::generic_string_model::{
|
||||
GenericStringModel, GenericStringObjectId, Serializer, StringModel,
|
||||
};
|
||||
use crate::cloud_object::model::persistence::{CloudModel, CloudModelEvent, UpdateSource};
|
||||
use crate::cloud_object::model::view::{CloudViewModel, Editor, EditorState};
|
||||
use crate::cloud_object::{
|
||||
CloudLinkSharing, CloudModelType, CloudObject, CloudObjectEventEntrypoint, CloudObjectLocation,
|
||||
CloudObjectSyncStatus, CreateCloudObjectResult, CreateObjectRequest, GenericCloudObject,
|
||||
GenericServerObject, GenericStringObjectFormat, JsonObjectType, NumInFlightRequests,
|
||||
ObjectDeleteResult, ObjectIdType, ObjectMetadataUpdateResult, ObjectPermissionsUpdateData,
|
||||
ObjectType, Owner, Revision, RevisionAndLastEditor, ServerAIExecutionProfile, ServerAIFact,
|
||||
ServerAmbientAgentEnvironment, ServerCloudAgentConfig, ServerCloudObject,
|
||||
ServerEnvVarCollection, ServerMCPServer, ServerMetadata, ServerPermissions, ServerPreference,
|
||||
ServerScheduledAmbientAgent, ServerTemplatableMCPServer, ServerWorkflowEnum, Space,
|
||||
UpdateCloudObjectResult,
|
||||
};
|
||||
use crate::drive::drive_helpers::{
|
||||
is_feature_gated_anonymous_user_past_env_var_limit,
|
||||
is_feature_gated_anonymous_user_past_notebook_limit,
|
||||
is_feature_gated_anonymous_user_past_workflow_limit,
|
||||
};
|
||||
use crate::drive::folders::{CloudFolderModel, FolderId};
|
||||
use crate::drive::sharing::SharingAccessLevel;
|
||||
use crate::drive::CloudObjectTypeAndId;
|
||||
use crate::env_vars::{CloudEnvVarCollectionModel, EnvVarCollection};
|
||||
use crate::network::{NetworkStatus, NetworkStatusEvent, NetworkStatusKind};
|
||||
use crate::notebooks::{CloudNotebookModel, NotebookId};
|
||||
use crate::persistence::ModelEvent;
|
||||
use crate::server::ids::{
|
||||
parse_sqlite_id_to_uid, ClientId, HashableId, HashedSqliteId, ObjectUid, ServerId, SyncId,
|
||||
ToServerId,
|
||||
};
|
||||
use crate::server::retry_strategies::{
|
||||
OUT_OF_BAND_REQUEST_RETRY_STRATEGY, PERIODIC_POLL, PERIODIC_POLL_RETRY_STRATEGY,
|
||||
};
|
||||
use crate::server::server_api::object::{GuestIdentifier, ObjectClient};
|
||||
use crate::server::sync_queue::{
|
||||
CreationFailureReason, GenericStringObjectToCreate, QueueItem, SyncQueue, SyncQueueEvent,
|
||||
};
|
||||
use crate::settings::cloud_preferences::Preference;
|
||||
use crate::workflows::workflow::Workflow;
|
||||
use crate::workflows::workflow_enum::{CloudWorkflowEnum, CloudWorkflowEnumModel, WorkflowEnum};
|
||||
use crate::workflows::{CloudWorkflowModel, WorkflowId};
|
||||
use crate::workspaces::team_tester::{TeamTesterStatus, TeamTesterStatusEvent};
|
||||
use crate::workspaces::update_manager::TeamUpdateManager;
|
||||
use crate::workspaces::user_profiles::{UserProfileWithUID, UserProfiles};
|
||||
use crate::workspaces::user_workspaces::UserWorkspaces;
|
||||
|
||||
lazy_static! {
|
||||
/// For online-only operations, we want to quickly determine if the operation can succeed,
|
||||
@@ -135,10 +139,19 @@ pub struct ObjectOperationResult {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UpdateManagerEvent {
|
||||
ObjectOperationComplete { result: ObjectOperationResult },
|
||||
CloudPreferencesUpdated { updated: Vec<Preference> },
|
||||
MCPGalleryUpdated { templates: Vec<MCPGalleryTemplate> },
|
||||
AmbientTaskUpdated { timestamp: DateTime<Utc> },
|
||||
ObjectOperationComplete {
|
||||
result: ObjectOperationResult,
|
||||
},
|
||||
CloudPreferencesUpdated {
|
||||
updated: Vec<Preference>,
|
||||
},
|
||||
MCPGalleryUpdated {
|
||||
templates: Vec<MCPGalleryTemplate>,
|
||||
},
|
||||
AmbientTaskUpdated {
|
||||
task_id: AmbientAgentTaskId,
|
||||
timestamp: DateTime<Utc>,
|
||||
},
|
||||
}
|
||||
|
||||
/// An enum for choosing the behavior of the fetch_single_cloud_object function.
|
||||
@@ -159,27 +172,6 @@ pub enum InitiatedBy {
|
||||
User,
|
||||
System,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct InitialLoadResponse {
|
||||
pub updated_notebooks: Vec<ServerNotebook>,
|
||||
pub deleted_notebooks: Vec<NotebookId>,
|
||||
pub updated_workflows: Vec<ServerWorkflow>,
|
||||
pub deleted_workflows: Vec<WorkflowId>,
|
||||
pub updated_folders: Vec<ServerFolder>,
|
||||
pub deleted_folders: Vec<FolderId>,
|
||||
pub updated_generic_string_objects:
|
||||
HashMap<GenericStringObjectFormat, Vec<Box<dyn ServerObject>>>,
|
||||
pub deleted_generic_string_objects: Vec<GenericStringObjectId>,
|
||||
pub user_profiles: Vec<UserProfileWithUID>,
|
||||
pub action_histories: Vec<ObjectActionHistory>,
|
||||
pub mcp_gallery: Vec<MCPGalleryTemplate>,
|
||||
}
|
||||
|
||||
pub struct GetCloudObjectResponse {
|
||||
pub object: ServerCloudObject,
|
||||
pub descendants: Vec<ServerCloudObject>,
|
||||
pub action_histories: Vec<ObjectActionHistory>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GenericStringObjectInput<T, S>
|
||||
@@ -218,7 +210,7 @@ impl UpdateManager {
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
let network_status = NetworkStatus::handle(ctx);
|
||||
ctx.subscribe_to_model(&network_status, |me, event, ctx| {
|
||||
ctx.subscribe_to_model(&network_status, |me, _, event, ctx| {
|
||||
me.handle_network_status_changed(event, ctx);
|
||||
});
|
||||
|
||||
@@ -226,7 +218,7 @@ impl UpdateManager {
|
||||
ctx.subscribe_to_model(&team_tester_status, Self::handle_team_tester_status_changed);
|
||||
|
||||
let sync_queue = SyncQueue::handle(ctx);
|
||||
ctx.subscribe_to_model(&sync_queue, |me, event, ctx| {
|
||||
ctx.subscribe_to_model(&sync_queue, |me, _, event, ctx| {
|
||||
me.handle_model_event(event, ctx);
|
||||
});
|
||||
|
||||
@@ -316,6 +308,7 @@ impl UpdateManager {
|
||||
|
||||
fn handle_team_tester_status_changed(
|
||||
&mut self,
|
||||
_: ModelHandle<TeamTesterStatus>,
|
||||
event: &TeamTesterStatusEvent,
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) {
|
||||
@@ -422,7 +415,7 @@ impl UpdateManager {
|
||||
}
|
||||
});
|
||||
|
||||
// Delete the actions on the client ID. Once we get a server ID for an object, we start dequeing any pending object actions and those
|
||||
// Delete the actions on the client ID. Once we get a server ID for an object, we start dequeuing any pending object actions and those
|
||||
// directly populate the ObjectActions model with the server ID, so we don't need to worry about any conversion or anything like that.
|
||||
ObjectActions::handle(ctx).update(ctx, |object_actions, ctx| {
|
||||
object_actions.delete_actions_for_object(&client_id.to_string(), ctx);
|
||||
@@ -1118,11 +1111,20 @@ impl UpdateManager {
|
||||
|
||||
fn handle_ambient_task_changed(
|
||||
&mut self,
|
||||
_task_id: String,
|
||||
task_id: String,
|
||||
timestamp: DateTime<Utc>,
|
||||
ctx: &mut ModelContext<UpdateManager>,
|
||||
) {
|
||||
ctx.emit(UpdateManagerEvent::AmbientTaskUpdated { timestamp });
|
||||
let task_id = match task_id.parse::<AmbientAgentTaskId>() {
|
||||
Ok(task_id) => task_id,
|
||||
Err(err) => {
|
||||
report_error!(anyhow::Error::from(err).context(format!(
|
||||
"AmbientTaskUpdated has unparseable task_id: {task_id}"
|
||||
)));
|
||||
return;
|
||||
}
|
||||
};
|
||||
ctx.emit(UpdateManagerEvent::AmbientTaskUpdated { task_id, timestamp });
|
||||
}
|
||||
|
||||
/// Fetches environment "last used" timestamps from the server and merges them
|
||||
@@ -1178,7 +1180,12 @@ impl UpdateManager {
|
||||
)
|
||||
});
|
||||
|
||||
GenericCloudObject::<K, M>::bulk_upsert_event(&objects_without_pending_changes)
|
||||
M::bulk_upsert_event(
|
||||
objects_without_pending_changes
|
||||
.iter()
|
||||
.map(|object| object.upsert_params(object.object_type()))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Generic handler deleting all objects of a given model type from the server (e.g. all updated/deleted notebooks or workflows).
|
||||
@@ -2877,7 +2884,7 @@ impl UpdateManager {
|
||||
let cloud_model = CloudModel::as_ref(ctx);
|
||||
let object: Option<&CloudWorkflowEnum> = cloud_model.get_object_of_type(enum_id);
|
||||
let Some(object) = object else {
|
||||
log::error!("Could not find referenced worfklow enum to copy over to the new space, skipping");
|
||||
log::error!("Could not find referenced workflow enum to copy over to the new space, skipping");
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -3216,6 +3223,25 @@ impl UpdateManager {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(target_family = "wasm", allow(dead_code))]
|
||||
pub fn create_ambient_agent_environment_online(
|
||||
&mut self,
|
||||
ambient_agent_environment: AmbientAgentEnvironment,
|
||||
client_id: ClientId,
|
||||
owner: Owner,
|
||||
ctx: &mut ModelContext<Self>,
|
||||
) -> impl Future<Output = anyhow::Result<ServerId>> {
|
||||
self.create_object_online(
|
||||
CloudAmbientAgentEnvironmentModel::new(ambient_agent_environment),
|
||||
owner,
|
||||
client_id,
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(target_family = "wasm", allow(dead_code))]
|
||||
pub fn create_scheduled_ambient_agent_online(
|
||||
&mut self,
|
||||
@@ -3320,10 +3346,10 @@ impl UpdateManager {
|
||||
.count()
|
||||
});
|
||||
if AuthStateProvider::handle(ctx).read(ctx, |auth_state_provider, _ctx| {
|
||||
auth_state_provider
|
||||
.get()
|
||||
.is_anonymous_user_past_object_limit(ObjectType::Notebook, count + 1)
|
||||
.unwrap_or_default()
|
||||
is_feature_gated_anonymous_user_past_notebook_limit(
|
||||
auth_state_provider.get(),
|
||||
count + 1,
|
||||
)
|
||||
}) {
|
||||
AuthManager::handle(ctx).update(ctx, |auth_manager: &mut AuthManager, ctx| {
|
||||
auth_manager.anonymous_user_hit_drive_object_limit(ctx);
|
||||
@@ -3391,10 +3417,10 @@ impl UpdateManager {
|
||||
.count()
|
||||
});
|
||||
if AuthStateProvider::handle(ctx).read(ctx, |auth_state_provider, _ctx| {
|
||||
auth_state_provider
|
||||
.get()
|
||||
.is_anonymous_user_past_object_limit(ObjectType::Workflow, count + 1)
|
||||
.unwrap_or_default()
|
||||
is_feature_gated_anonymous_user_past_workflow_limit(
|
||||
auth_state_provider.get(),
|
||||
count + 1,
|
||||
)
|
||||
}) {
|
||||
AuthManager::handle(ctx).update(ctx, |auth_manager: &mut AuthManager, ctx| {
|
||||
auth_manager.anonymous_user_hit_drive_object_limit(ctx);
|
||||
@@ -3456,14 +3482,8 @@ impl UpdateManager {
|
||||
.active_non_welcome_env_var_collections_in_space(Space::Personal, ctx)
|
||||
.count()
|
||||
});
|
||||
let env_var_collection_type = ObjectType::GenericStringObject(
|
||||
GenericStringObjectFormat::Json(JsonObjectType::EnvVarCollection),
|
||||
);
|
||||
if AuthStateProvider::handle(ctx).read(ctx, |auth_state_provider, _ctx| {
|
||||
auth_state_provider
|
||||
.get()
|
||||
.is_anonymous_user_past_object_limit(env_var_collection_type, count + 1)
|
||||
.unwrap_or_default()
|
||||
is_feature_gated_anonymous_user_past_env_var_limit(auth_state_provider.get(), count + 1)
|
||||
}) {
|
||||
AuthManager::handle(ctx).update(ctx, |auth_manager: &mut AuthManager, ctx| {
|
||||
auth_manager.anonymous_user_hit_drive_object_limit(ctx);
|
||||
@@ -3571,7 +3591,10 @@ impl UpdateManager {
|
||||
|
||||
// Update sqlite with a single bulk request
|
||||
self.save_to_db(vec![GenericStringModel::<T, S>::bulk_upsert_event(
|
||||
&objects,
|
||||
objects
|
||||
.iter()
|
||||
.map(|object| object.upsert_params(object.object_type()))
|
||||
.collect(),
|
||||
)]);
|
||||
|
||||
// Populate sync queue with a single bulk request
|
||||
@@ -4825,5 +4848,5 @@ impl Entity for UpdateManager {
|
||||
impl SingletonEntity for UpdateManager {}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "update_manager_test.rs"]
|
||||
#[path = "update_manager_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
+189
-194
@@ -1,69 +1,62 @@
|
||||
use std::{collections::HashMap, sync::Arc, time::Duration};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use cloud_object_client::MockObjectClient;
|
||||
use cloud_object_models::JsonSerializer;
|
||||
use futures_lite::future;
|
||||
use settings::{RespectUserSyncSetting, SyncToCloud};
|
||||
use galaxy_core::features::FeatureFlag;
|
||||
use galaxy_graphql::{object_permissions::AccessLevel, scalars::time::ServerTimestamp};
|
||||
use galaxy_graphql::object_permissions::AccessLevel;
|
||||
use galaxy_graphql::scalars::time::ServerTimestamp;
|
||||
use galaxyui::{App, ModelHandle, SingletonEntity};
|
||||
use settings::SyncToCloud;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::server::server_api::object::MockObjectClient;
|
||||
use crate::{
|
||||
ai::cloud_environments::{
|
||||
AmbientAgentEnvironment, CloudAmbientAgentEnvironment, CloudAmbientAgentEnvironmentModel,
|
||||
},
|
||||
auth::{user::TEST_USER_UID, UserUid},
|
||||
cloud_object::{
|
||||
model::{
|
||||
actions::{
|
||||
ObjectAction, ObjectActionHistory, ObjectActionSubtype, ObjectActionType,
|
||||
ObjectActions,
|
||||
},
|
||||
generic_string_model::GenericStringObjectId,
|
||||
json_model::JsonSerializer,
|
||||
persistence::{CloudModel, CloudModelEvent, UpdateSource},
|
||||
},
|
||||
BulkCreateCloudObjectResult, CloudModelType, CloudObjectEventEntrypoint, CloudObjectGuest,
|
||||
CloudObjectLocation, ConflictStatus, CreateCloudObjectResult, CreatedCloudObject,
|
||||
GenericCloudObject, GenericStringObjectFormat, JsonObjectType, ObjectDeleteResult,
|
||||
ObjectIdType, ObjectMetadataUpdateResult, ObjectPermissionsUpdateData, ObjectType, Owner,
|
||||
Revision, RevisionAndLastEditor, ServerCloudObject, ServerFolder, ServerGuestSubject,
|
||||
ServerObject, ServerObjectGuest, ServerPreference, ServerWorkflow, ServerWorkflowEnum,
|
||||
Space, UpdateCloudObjectResult,
|
||||
},
|
||||
drive::{
|
||||
folders::{CloudFolder, CloudFolderModel, FolderId},
|
||||
sharing::{SharingAccessLevel, Subject, UserKind},
|
||||
CloudObjectTypeAndId,
|
||||
},
|
||||
notebooks::{CloudNotebook, CloudNotebookModel, NotebookId},
|
||||
persistence::ModelEvent,
|
||||
server::{
|
||||
cloud_objects::{
|
||||
listener::ObjectUpdateMessage,
|
||||
test_utils::{
|
||||
create_update_manager_struct, initialize_app, mock_server_api, UpdateManagerStruct,
|
||||
},
|
||||
update_manager::{
|
||||
get_duplicate_object_name, FetchSingleObjectOption, GenericStringObjectInput,
|
||||
InitiatedBy, ServerMetadata, ServerNotebook, ServerPermissions,
|
||||
},
|
||||
},
|
||||
ids::{ClientId, HashableId, ObjectUid, ServerId, ServerIdAndType, SyncId, ToServerId},
|
||||
sync_queue::SyncQueue,
|
||||
},
|
||||
settings::{CloudPreferenceModel, Preference},
|
||||
workflows::{
|
||||
workflow::{Argument, ArgumentType, Workflow},
|
||||
workflow_enum::{CloudWorkflowEnum, CloudWorkflowEnumModel, EnumVariants, WorkflowEnum},
|
||||
CloudWorkflow, CloudWorkflowModel, WorkflowId,
|
||||
},
|
||||
workspaces::user_profiles::{UserProfileWithUID, UserProfiles},
|
||||
Assets,
|
||||
};
|
||||
|
||||
use super::{GetCloudObjectResponse, InitialLoadResponse, UpdateManager};
|
||||
use crate::ai::cloud_environments::{
|
||||
AmbientAgentEnvironment, CloudAmbientAgentEnvironment, CloudAmbientAgentEnvironmentModel,
|
||||
};
|
||||
use crate::auth::user::TEST_USER_UID;
|
||||
use crate::auth::UserUid;
|
||||
use crate::cloud_object::model::actions::{
|
||||
ObjectAction, ObjectActionHistory, ObjectActionSubtype, ObjectActionType, ObjectActions,
|
||||
};
|
||||
use crate::cloud_object::model::generic_string_model::GenericStringObjectId;
|
||||
use crate::cloud_object::model::persistence::{CloudModel, CloudModelEvent, UpdateSource};
|
||||
use crate::cloud_object::{
|
||||
BulkCreateCloudObjectResult, CloudModelType, CloudObjectEventEntrypoint, CloudObjectGuest,
|
||||
CloudObjectLocation, ConflictStatus, CreateCloudObjectResult, CreatedCloudObject,
|
||||
GenericCloudObject, GenericStringObjectFormat, JsonObjectType, ObjectDeleteResult,
|
||||
ObjectIdType, ObjectMetadataUpdateResult, ObjectPermissionsUpdateData, ObjectType, Owner,
|
||||
Revision, RevisionAndLastEditor, ServerCloudObject, ServerFolder, ServerGuestSubject,
|
||||
ServerNotebook, ServerObject, ServerObjectGuest, ServerPreference, ServerWorkflow,
|
||||
ServerWorkflowEnum, Space, UpdateCloudObjectResult,
|
||||
};
|
||||
use crate::drive::folders::{CloudFolder, CloudFolderModel, FolderId};
|
||||
use crate::drive::sharing::{SharingAccessLevel, Subject, UserKind};
|
||||
use crate::drive::CloudObjectTypeAndId;
|
||||
use crate::notebooks::{CloudNotebook, CloudNotebookModel, NotebookId};
|
||||
use crate::persistence::ModelEvent;
|
||||
use crate::server::cloud_objects::listener::ObjectUpdateMessage;
|
||||
use crate::server::cloud_objects::test_utils::{
|
||||
create_update_manager_struct, initialize_app, mock_server_api, UpdateManagerStruct,
|
||||
};
|
||||
use crate::server::cloud_objects::update_manager::{
|
||||
get_duplicate_object_name, FetchSingleObjectOption, GenericStringObjectInput, InitiatedBy,
|
||||
ServerMetadata, ServerPermissions,
|
||||
};
|
||||
use crate::server::ids::{
|
||||
ClientId, HashableId, ObjectUid, ServerId, ServerIdAndType, SyncId, ToServerId,
|
||||
};
|
||||
use crate::server::sync_queue::SyncQueue;
|
||||
use crate::settings::{CloudPreferenceModel, Preference};
|
||||
use crate::workflows::workflow::{Argument, ArgumentType, Workflow};
|
||||
use crate::workflows::workflow_enum::{
|
||||
CloudWorkflowEnum, CloudWorkflowEnumModel, EnumVariants, WorkflowEnum,
|
||||
};
|
||||
use crate::workflows::{CloudWorkflow, CloudWorkflowModel, WorkflowId};
|
||||
use crate::workspaces::user_profiles::{UserProfileWithUID, UserProfiles};
|
||||
use crate::ASSETS;
|
||||
|
||||
fn create_object<K, M>(
|
||||
app: &mut App,
|
||||
@@ -261,12 +254,12 @@ fn create_workflow_enum_internal(
|
||||
}
|
||||
|
||||
fn mock_server_workflow(id: WorkflowId, owner: Owner, metadata: ServerMetadata) -> ServerWorkflow {
|
||||
ServerWorkflow {
|
||||
id: SyncId::ServerId(id.into()),
|
||||
ServerWorkflow::new(
|
||||
SyncId::ServerId(id.into()),
|
||||
CloudWorkflowModel::new(Workflow::new(format!("w{id}"), format!("c{id}"))),
|
||||
metadata,
|
||||
permissions: mock_server_permissions(owner),
|
||||
model: CloudWorkflowModel::new(Workflow::new(format!("w{id}"), format!("c{id}"))),
|
||||
}
|
||||
mock_server_permissions(owner),
|
||||
)
|
||||
}
|
||||
|
||||
fn mock_server_workflow_with_enum(
|
||||
@@ -275,11 +268,9 @@ fn mock_server_workflow_with_enum(
|
||||
owner: Owner,
|
||||
metadata: ServerMetadata,
|
||||
) -> (ServerWorkflow, ServerWorkflowEnum) {
|
||||
let workflow = ServerWorkflow {
|
||||
id: SyncId::ServerId(id.into()),
|
||||
metadata: metadata.clone(),
|
||||
permissions: mock_server_permissions(owner),
|
||||
model: CloudWorkflowModel::new(
|
||||
let workflow = ServerWorkflow::new(
|
||||
SyncId::ServerId(id.into()),
|
||||
CloudWorkflowModel::new(
|
||||
Workflow::new(format!("w{id}"), format!("c{id}")).with_arguments(vec![Argument {
|
||||
name: format!("e{enum_id}"),
|
||||
default_value: None,
|
||||
@@ -289,47 +280,49 @@ fn mock_server_workflow_with_enum(
|
||||
},
|
||||
}]),
|
||||
),
|
||||
};
|
||||
metadata.clone(),
|
||||
mock_server_permissions(owner),
|
||||
);
|
||||
|
||||
let workflow_enum = ServerWorkflowEnum {
|
||||
id: SyncId::ServerId(enum_id.into()),
|
||||
metadata,
|
||||
permissions: mock_server_permissions(owner),
|
||||
model: CloudWorkflowEnumModel::new(WorkflowEnum {
|
||||
let workflow_enum = ServerWorkflowEnum::new(
|
||||
SyncId::ServerId(enum_id.into()),
|
||||
CloudWorkflowEnumModel::new(WorkflowEnum {
|
||||
name: format!("e{id}"),
|
||||
is_shared: false,
|
||||
variants: EnumVariants::Static(vec!["v1".to_string(), "v2".to_string()]),
|
||||
}),
|
||||
};
|
||||
metadata,
|
||||
mock_server_permissions(owner),
|
||||
);
|
||||
|
||||
(workflow, workflow_enum)
|
||||
}
|
||||
|
||||
fn mock_server_notebook(id: NotebookId, owner: Owner, metadata: ServerMetadata) -> ServerNotebook {
|
||||
ServerNotebook {
|
||||
id: SyncId::ServerId(id.into()),
|
||||
metadata,
|
||||
permissions: mock_server_permissions(owner),
|
||||
model: CloudNotebookModel {
|
||||
ServerNotebook::new(
|
||||
SyncId::ServerId(id.into()),
|
||||
CloudNotebookModel {
|
||||
title: format!("n{id}"),
|
||||
data: format!("n{id}"),
|
||||
ai_document_id: None,
|
||||
conversation_id: None,
|
||||
},
|
||||
}
|
||||
metadata,
|
||||
mock_server_permissions(owner),
|
||||
)
|
||||
}
|
||||
|
||||
fn mock_server_folder(id: FolderId, owner: Owner, metadata: ServerMetadata) -> ServerFolder {
|
||||
ServerFolder {
|
||||
id: SyncId::ServerId(id.into()),
|
||||
metadata,
|
||||
permissions: mock_server_permissions(owner),
|
||||
model: CloudFolderModel {
|
||||
ServerFolder::new(
|
||||
SyncId::ServerId(id.into()),
|
||||
CloudFolderModel {
|
||||
name: format!("f{id}"),
|
||||
is_open: false,
|
||||
is_warp_pack: false,
|
||||
},
|
||||
}
|
||||
metadata,
|
||||
mock_server_permissions(owner),
|
||||
)
|
||||
}
|
||||
|
||||
fn update_notebook(
|
||||
@@ -603,10 +596,10 @@ fn mock_fetch_single_cloud_object(
|
||||
.times(1)
|
||||
.return_once(move |_| {
|
||||
Ok(GetCloudObjectResponse {
|
||||
object: ServerCloudObject::Workflow(Box::new(ServerWorkflow {
|
||||
id: SyncId::ServerId(workflow_id.into()),
|
||||
model: CloudWorkflowModel::new(Workflow::new("server workflow", "echo server")),
|
||||
metadata: ServerMetadata {
|
||||
object: ServerCloudObject::Workflow(Box::new(ServerWorkflow::new(
|
||||
SyncId::ServerId(workflow_id.into()),
|
||||
CloudWorkflowModel::new(Workflow::new("server workflow", "echo server")),
|
||||
ServerMetadata {
|
||||
uid: server_id,
|
||||
revision: Revision::now(),
|
||||
metadata_last_updated_ts: Utc::now().into(),
|
||||
@@ -617,13 +610,13 @@ fn mock_fetch_single_cloud_object(
|
||||
last_editor_uid: None,
|
||||
current_editor_uid: None,
|
||||
},
|
||||
permissions: ServerPermissions {
|
||||
ServerPermissions {
|
||||
space: Owner::mock_current_user(),
|
||||
guests: Vec::new(),
|
||||
anyone_link_sharing: None,
|
||||
permissions_last_updated_ts: Utc::now().into(),
|
||||
},
|
||||
})),
|
||||
))),
|
||||
descendants: vec![],
|
||||
action_histories: vec![ObjectActionHistory {
|
||||
uid: server_id.uid(),
|
||||
@@ -637,7 +630,7 @@ fn mock_fetch_single_cloud_object(
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_item_not_in_sync_queue_folder() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
let client_id = ClientId::new();
|
||||
initialize_app(&mut app);
|
||||
let object_id: FolderId = 123.into();
|
||||
@@ -665,7 +658,7 @@ fn test_sync_state_after_creation_item_not_in_sync_queue_folder() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_item_not_in_sync_queue_workflow() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
let client_id = ClientId::new();
|
||||
initialize_app(&mut app);
|
||||
let object_id: WorkflowId = 123.into();
|
||||
@@ -693,7 +686,7 @@ fn test_sync_state_after_creation_item_not_in_sync_queue_workflow() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_item_not_in_sync_queue_notebook() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
let client_id = ClientId::new();
|
||||
initialize_app(&mut app);
|
||||
|
||||
@@ -722,7 +715,7 @@ fn test_sync_state_after_creation_item_not_in_sync_queue_notebook() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_item_not_in_sync_queue_generic_object() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
let client_id = ClientId::new();
|
||||
initialize_app(&mut app);
|
||||
let object_id: GenericStringObjectId = 123.into();
|
||||
@@ -806,7 +799,9 @@ async fn run_sync_state_after_creation_item_not_in_sync_queue<K, M>(
|
||||
// we created an object in the db
|
||||
assert_eq!(
|
||||
std::mem::discriminant(&events[0]),
|
||||
std::mem::discriminant(&object.model().upsert_event(&object))
|
||||
std::mem::discriminant(&M::upsert_event(
|
||||
object.upsert_params(object.model().object_type())
|
||||
))
|
||||
);
|
||||
// when we got the correct response back from the server,
|
||||
// we updated the db with the server id
|
||||
@@ -834,7 +829,7 @@ async fn run_sync_state_after_creation_item_not_in_sync_queue<K, M>(
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_item_in_flight() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -921,7 +916,7 @@ fn test_sync_state_after_creation_item_in_flight() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_fails_due_to_limit() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let client_id = ClientId::new();
|
||||
@@ -1046,7 +1041,7 @@ fn test_sync_state_after_creation_fails_due_to_limit() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_update_item_not_in_sync_queue() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -1191,7 +1186,7 @@ fn test_sync_state_after_update_item_not_in_sync_queue() {
|
||||
|
||||
#[test]
|
||||
fn test_create_sets_editor() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = mock_server_api();
|
||||
@@ -1235,7 +1230,7 @@ fn test_create_sets_editor() {
|
||||
|
||||
#[test]
|
||||
fn test_bulk_create_generic_string_objects() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let client_id_1 = ClientId::new();
|
||||
@@ -1393,7 +1388,7 @@ fn test_bulk_create_generic_string_objects() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_update_item_not_in_sync_queue_generic_string_object() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let client_id = ClientId::new();
|
||||
@@ -1524,7 +1519,7 @@ fn test_sync_state_after_update_item_not_in_sync_queue_generic_string_object() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_update_item_in_sync_queue() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -1641,7 +1636,7 @@ fn test_sync_state_after_update_item_in_sync_queue() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_creation_failure_item_not_in_sync_queue() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -1687,7 +1682,7 @@ fn test_sync_state_after_creation_failure_item_not_in_sync_queue() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_update_failure_item_in_sync_queue() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -1808,7 +1803,7 @@ fn test_sync_state_after_update_failure_item_in_sync_queue() {
|
||||
|
||||
#[test]
|
||||
fn test_sync_state_after_object_with_dependencies_created() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -1958,7 +1953,7 @@ fn test_sync_state_after_object_with_dependencies_created() {
|
||||
|
||||
#[test]
|
||||
fn test_fetch_single_cloud_object_not_pending_no_overwrite() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let client_id = ClientId::new();
|
||||
@@ -2054,7 +2049,7 @@ fn test_fetch_single_cloud_object_not_pending_no_overwrite() {
|
||||
|
||||
#[test]
|
||||
fn test_fetch_single_cloud_object_pending_no_overwrite() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -2154,7 +2149,7 @@ fn test_fetch_single_cloud_object_pending_no_overwrite() {
|
||||
|
||||
#[test]
|
||||
fn test_fetch_single_cloud_object_pending_with_overwrite() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -2260,7 +2255,7 @@ fn test_fetch_single_cloud_object_pending_with_overwrite() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_trash_item_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -2330,7 +2325,7 @@ fn test_metadata_after_trash_item_success() {
|
||||
|
||||
#[test]
|
||||
fn test_pending_metadata_update_with_rtc() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -2397,7 +2392,7 @@ fn test_pending_metadata_update_with_rtc() {
|
||||
mocked_metadata_update_message,
|
||||
);
|
||||
|
||||
// Assert we don't have a pending change now that we've updated the metadat
|
||||
// Assert we don't have a pending change now that we've updated the metadata
|
||||
assert_pending_online_only_change_for_object(
|
||||
&mut app,
|
||||
¬ebook_id.to_server_id().uid(),
|
||||
@@ -2437,7 +2432,7 @@ fn test_pending_metadata_update_with_rtc() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_update_with_rtc_no_pending() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -2535,7 +2530,7 @@ fn test_metadata_update_with_rtc_no_pending() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_trash_item_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -2604,7 +2599,7 @@ fn test_metadata_after_trash_item_failure() {
|
||||
|
||||
#[test]
|
||||
fn test_pending_metadata_update_with_polling() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -2673,9 +2668,9 @@ fn test_pending_metadata_update_with_polling() {
|
||||
> = HashMap::new();
|
||||
updated_generic_string_objects.insert(
|
||||
GenericStringObjectFormat::Json(JsonObjectType::Preference),
|
||||
vec![Box::new(ServerPreference {
|
||||
id: SyncId::ServerId(generic_object_server_id),
|
||||
model: CloudPreferenceModel::new(
|
||||
vec![Box::new(ServerPreference::new(
|
||||
SyncId::ServerId(generic_object_server_id),
|
||||
CloudPreferenceModel::new(
|
||||
Preference::new(
|
||||
"test_storage_key".to_string(),
|
||||
"{\"test_key\": \"test_value\"}",
|
||||
@@ -2683,23 +2678,23 @@ fn test_pending_metadata_update_with_polling() {
|
||||
)
|
||||
.expect("error creating preference"),
|
||||
),
|
||||
metadata: mocked_metadata.clone(),
|
||||
permissions: mock_server_permissions(Owner::mock_current_user()),
|
||||
})],
|
||||
mocked_metadata.clone(),
|
||||
mock_server_permissions(Owner::mock_current_user()),
|
||||
))],
|
||||
);
|
||||
|
||||
let mocked_response = InitialLoadResponse {
|
||||
updated_notebooks: vec![ServerNotebook {
|
||||
id: SyncId::ServerId(notebood_server_id),
|
||||
model: CloudNotebookModel {
|
||||
updated_notebooks: vec![ServerNotebook::new(
|
||||
SyncId::ServerId(notebood_server_id),
|
||||
CloudNotebookModel {
|
||||
title: "".into(),
|
||||
data: "".into(),
|
||||
ai_document_id: None,
|
||||
conversation_id: None,
|
||||
},
|
||||
metadata: mocked_metadata.clone(),
|
||||
permissions: mock_server_permissions(Owner::mock_current_user()),
|
||||
}],
|
||||
mocked_metadata.clone(),
|
||||
mock_server_permissions(Owner::mock_current_user()),
|
||||
)],
|
||||
deleted_notebooks: vec![],
|
||||
updated_workflows: vec![],
|
||||
deleted_workflows: vec![],
|
||||
@@ -2757,7 +2752,7 @@ fn test_pending_metadata_update_with_polling() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_update_with_polling_no_pending() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -2806,17 +2801,17 @@ fn test_metadata_update_with_polling_no_pending() {
|
||||
current_editor_uid: Some("ian@warp.dev".to_string()),
|
||||
};
|
||||
let mocked_response = InitialLoadResponse {
|
||||
updated_notebooks: vec![ServerNotebook {
|
||||
id: SyncId::ServerId(server_id),
|
||||
model: CloudNotebookModel {
|
||||
updated_notebooks: vec![ServerNotebook::new(
|
||||
SyncId::ServerId(server_id),
|
||||
CloudNotebookModel {
|
||||
title: "".into(),
|
||||
data: "".into(),
|
||||
ai_document_id: None,
|
||||
conversation_id: None,
|
||||
},
|
||||
metadata: mocked_metadata.clone(),
|
||||
permissions: mock_server_permissions(Owner::mock_current_user()),
|
||||
}],
|
||||
mocked_metadata.clone(),
|
||||
mock_server_permissions(Owner::mock_current_user()),
|
||||
)],
|
||||
deleted_notebooks: vec![],
|
||||
updated_workflows: vec![],
|
||||
deleted_workflows: vec![],
|
||||
@@ -2874,7 +2869,7 @@ fn test_metadata_update_with_polling_no_pending() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_untrash_item_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -2944,7 +2939,7 @@ fn test_metadata_after_untrash_item_success() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_untrash_item_and_move_to_root() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -3017,7 +3012,7 @@ fn test_metadata_after_untrash_item_and_move_to_root() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_untrash_item_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -3071,7 +3066,7 @@ fn test_metadata_after_untrash_item_failure() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_optimistic_grab_baton_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -3143,7 +3138,7 @@ fn test_metadata_after_optimistic_grab_baton_success() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_optimistic_grab_baton_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -3202,7 +3197,7 @@ fn test_metadata_after_optimistic_grab_baton_failure() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_non_optimistic_grab_baton_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -3274,7 +3269,7 @@ fn test_metadata_after_non_optimistic_grab_baton_success() {
|
||||
|
||||
#[test]
|
||||
fn test_metadata_after_non_optimistic_grab_baton_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -3332,7 +3327,7 @@ fn test_metadata_after_non_optimistic_grab_baton_failure() {
|
||||
|
||||
#[test]
|
||||
fn test_report_initial_load() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let update_manager_struct = create_update_manager_struct(&mut app, Arc::new(server_api));
|
||||
@@ -3417,7 +3412,7 @@ fn test_get_duplicate_object_name() {
|
||||
|
||||
#[test]
|
||||
fn test_duplicate_workflow_not_pending_no_overwrite() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = mock_server_api();
|
||||
@@ -3497,7 +3492,7 @@ fn test_duplicate_workflow_not_pending_no_overwrite() {
|
||||
|
||||
#[test]
|
||||
fn test_replace_object_with_conflicts() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = mock_server_api();
|
||||
@@ -3614,7 +3609,7 @@ fn test_replace_object_with_conflicts() {
|
||||
|
||||
#[test]
|
||||
fn test_pending_conflict_correctly_clears_after_edits() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = mock_server_api();
|
||||
@@ -3673,7 +3668,7 @@ fn test_pending_conflict_correctly_clears_after_edits() {
|
||||
ModelEvent::UpsertNotebook { .. }
|
||||
));
|
||||
|
||||
// While we still have edits in flight, recieve an RTC message, that has a TS before the object update
|
||||
// While we still have edits in flight, receive an RTC message, that has a TS before the object update
|
||||
// response. This should put the notebook conflict status as pending
|
||||
let mocked_metadata = ServerMetadata {
|
||||
uid: server_id,
|
||||
@@ -3746,7 +3741,7 @@ fn test_pending_conflict_correctly_clears_after_edits() {
|
||||
|
||||
#[test]
|
||||
fn test_pending_conflict_correctly_stays_after_edits() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = mock_server_api();
|
||||
@@ -3805,7 +3800,7 @@ fn test_pending_conflict_correctly_stays_after_edits() {
|
||||
ModelEvent::UpsertNotebook { .. }
|
||||
));
|
||||
|
||||
// While we still have edits in flight, recieve an RTC message, that has a TS after the object update
|
||||
// While we still have edits in flight, receive an RTC message, that has a TS after the object update
|
||||
// response. This should put the notebook conflict status as pending
|
||||
let mocked_metadata = ServerMetadata {
|
||||
uid: server_id,
|
||||
@@ -3877,7 +3872,7 @@ fn test_pending_self_conflict_clears_out_of_order() {
|
||||
// This tests the case where the client makes an edit and receives the RTC update for it
|
||||
// _before_ the server response to their edit.
|
||||
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = MockObjectClient::new();
|
||||
@@ -3972,7 +3967,7 @@ fn test_pending_self_conflict_clears_out_of_order() {
|
||||
fn test_pending_newer_conflict_remains_out_of_order() {
|
||||
// This tests the case where the client makes an edit which is eventually accepted by the
|
||||
// server, but receives an RTC update about a _newer_ edit in the meantime.
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = MockObjectClient::new();
|
||||
@@ -4067,7 +4062,7 @@ fn test_pending_newer_conflict_remains_out_of_order() {
|
||||
|
||||
#[test]
|
||||
fn test_accepts_new_metadata_with_force_refresh() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let server_id: ServerId = 123.into();
|
||||
@@ -4107,17 +4102,17 @@ fn test_accepts_new_metadata_with_force_refresh() {
|
||||
current_editor_uid: None,
|
||||
};
|
||||
let mocked_response = InitialLoadResponse {
|
||||
updated_notebooks: vec![ServerNotebook {
|
||||
id: SyncId::ServerId(server_id),
|
||||
model: CloudNotebookModel {
|
||||
updated_notebooks: vec![ServerNotebook::new(
|
||||
SyncId::ServerId(server_id),
|
||||
CloudNotebookModel {
|
||||
title: "".into(),
|
||||
data: "".into(),
|
||||
ai_document_id: None,
|
||||
conversation_id: None,
|
||||
},
|
||||
metadata: mocked_metadata.clone(),
|
||||
permissions: mock_server_permissions(Owner::mock_current_user()),
|
||||
}],
|
||||
mocked_metadata.clone(),
|
||||
mock_server_permissions(Owner::mock_current_user()),
|
||||
)],
|
||||
deleted_notebooks: vec![],
|
||||
updated_workflows: vec![],
|
||||
deleted_workflows: vec![],
|
||||
@@ -4160,7 +4155,7 @@ fn test_accepts_new_metadata_with_force_refresh() {
|
||||
|
||||
#[test]
|
||||
fn test_delete_single_object() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4232,7 +4227,7 @@ fn test_delete_single_object() {
|
||||
|
||||
#[test]
|
||||
fn test_empty_trash() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let ts = Utc::now();
|
||||
@@ -4344,7 +4339,7 @@ fn test_empty_trash() {
|
||||
|
||||
#[test]
|
||||
fn test_leave_shared_object() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4451,7 +4446,7 @@ fn test_leave_shared_object() {
|
||||
|
||||
#[test]
|
||||
fn test_create_object_online_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4551,7 +4546,7 @@ fn test_create_object_online_success() {
|
||||
|
||||
#[test]
|
||||
fn test_create_object_online_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4610,7 +4605,7 @@ fn test_create_object_online_failure() {
|
||||
|
||||
#[test]
|
||||
fn test_create_object_online_user_facing_error() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4673,7 +4668,7 @@ fn test_create_object_online_user_facing_error() {
|
||||
|
||||
#[test]
|
||||
fn test_create_object_online_with_folder_id() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4756,7 +4751,7 @@ fn test_create_object_online_with_folder_id() {
|
||||
|
||||
#[test]
|
||||
fn test_create_object_online_with_client_folder_id_fails() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4808,7 +4803,7 @@ fn test_create_object_online_with_client_folder_id_fails() {
|
||||
|
||||
#[test]
|
||||
fn test_record_object_action() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -4895,7 +4890,7 @@ fn test_record_object_action() {
|
||||
|
||||
#[test]
|
||||
fn test_overwrite_object_action_history_no_actions_on_client() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -4963,7 +4958,7 @@ fn test_overwrite_object_action_history_no_actions_on_client() {
|
||||
|
||||
#[test]
|
||||
fn test_overwrite_object_action_history_reject() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -5117,7 +5112,7 @@ fn test_overwrite_object_action_history_reject() {
|
||||
|
||||
#[test]
|
||||
fn test_overwrite_object_action_history_ignores_pending_local_actions() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -5271,7 +5266,7 @@ fn test_overwrite_object_action_history_ignores_pending_local_actions() {
|
||||
|
||||
#[test]
|
||||
fn test_object_action_histories_with_initial_load() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
|
||||
@@ -5457,7 +5452,7 @@ fn test_object_action_histories_with_initial_load() {
|
||||
|
||||
#[test]
|
||||
fn test_delete_single_object_with_actions() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -5581,7 +5576,7 @@ fn test_delete_single_object_with_actions() {
|
||||
/// changing the owner of an object, which implicitly also clears its parent folder.
|
||||
#[test]
|
||||
fn test_move_object_personal_to_team_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -5681,7 +5676,7 @@ fn test_move_object_personal_to_team_success() {
|
||||
/// optimistically update the model, and then roll those updates back on failure.
|
||||
#[test]
|
||||
fn test_move_object_personal_to_team_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -5787,7 +5782,7 @@ fn test_move_object_personal_to_team_failure() {
|
||||
/// space to a team drive.
|
||||
#[test]
|
||||
fn test_move_cloud_environment_personal_to_team_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -5886,7 +5881,7 @@ fn test_move_cloud_environment_personal_to_team_success() {
|
||||
/// and change the reference stored within the workflow to point to that enum.
|
||||
#[test]
|
||||
fn test_move_workflow_with_enums_personal_to_team_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let team = Space::Team {
|
||||
@@ -6023,7 +6018,7 @@ fn test_move_workflow_with_enums_personal_to_team_success() {
|
||||
|
||||
#[test]
|
||||
fn test_move_workflow_with_enums_personal_to_team_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
let team = Space::Team {
|
||||
@@ -6174,7 +6169,7 @@ fn test_move_workflow_with_enums_personal_to_team_failure() {
|
||||
/// `Some`.
|
||||
#[test]
|
||||
fn test_move_object_root_to_folder_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -6267,7 +6262,7 @@ fn test_move_object_root_to_folder_success() {
|
||||
/// optimistically update the model, and then roll back the updates on failure.
|
||||
#[test]
|
||||
fn test_move_object_root_to_folder_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -6366,7 +6361,7 @@ fn test_move_object_root_to_folder_failure() {
|
||||
/// during, and after a move where the object's parent folder changes from `Some` to `None`.
|
||||
#[test]
|
||||
fn test_move_object_folder_to_root_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -6459,7 +6454,7 @@ fn test_move_object_folder_to_root_success() {
|
||||
/// we optimistically clear its parent folder, and then restore it on failure.
|
||||
#[test]
|
||||
fn test_move_object_folder_to_root_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -6558,7 +6553,7 @@ fn test_move_object_folder_to_root_failure() {
|
||||
/// checks that we update the object's metadata and emit events correctly.
|
||||
#[test]
|
||||
fn test_move_object_folder_to_folder_success() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -6653,7 +6648,7 @@ fn test_move_object_folder_to_folder_success() {
|
||||
/// we optimistically apply the move in-memory and then undo it on failure.
|
||||
#[test]
|
||||
fn test_move_object_folder_to_folder_failure() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -6754,7 +6749,7 @@ fn test_move_object_folder_to_folder_failure() {
|
||||
/// object was trashed by another client.
|
||||
#[test]
|
||||
fn test_trash_object_over_rtc() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let workflow_id: WorkflowId = 123.into();
|
||||
@@ -6831,7 +6826,7 @@ fn test_trash_object_over_rtc() {
|
||||
/// object was un-trashed by another client.
|
||||
#[test]
|
||||
fn test_untrash_object_over_rtc() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let workflow_id: WorkflowId = 123.into();
|
||||
@@ -6908,7 +6903,7 @@ fn test_untrash_object_over_rtc() {
|
||||
/// object was moved from one folder to another in the same space by another client.
|
||||
#[test]
|
||||
fn test_move_object_from_folder_to_folder_over_rtc() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let workflow_id: WorkflowId = 123.into();
|
||||
@@ -6989,7 +6984,7 @@ fn test_move_object_from_folder_to_folder_over_rtc() {
|
||||
/// object was moved from a folder to the root of its space by another client.
|
||||
#[test]
|
||||
fn test_move_object_from_folder_to_root_over_rtc() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let workflow_id: WorkflowId = 123.into();
|
||||
@@ -7069,7 +7064,7 @@ fn test_move_object_from_folder_to_root_over_rtc() {
|
||||
/// an object was moved from the root of its space into a folder by another client.
|
||||
#[test]
|
||||
fn test_move_object_from_root_to_folder_over_rtc() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let server_api = mock_server_api();
|
||||
let workflow_id: WorkflowId = 123.into();
|
||||
@@ -7147,7 +7142,7 @@ fn test_move_object_from_root_to_folder_over_rtc() {
|
||||
|
||||
#[test]
|
||||
fn test_permissions_update_grants_access() {
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let mut server_api = mock_server_api();
|
||||
@@ -7261,7 +7256,7 @@ fn test_permissions_update_grants_access() {
|
||||
fn test_permissions_update_existing_object() {
|
||||
let _guard = FeatureFlag::SharedWithMe.override_enabled(true);
|
||||
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
|
||||
let server_api = mock_server_api();
|
||||
@@ -7322,7 +7317,7 @@ fn test_permissions_update_existing_object() {
|
||||
#[test]
|
||||
fn test_add_guest_success() {
|
||||
let _guard = FeatureFlag::SharedWithMe.override_enabled(true);
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
@@ -7436,7 +7431,7 @@ fn test_add_guest_success() {
|
||||
#[test]
|
||||
fn test_add_guest_failure() {
|
||||
let _guard = FeatureFlag::SharedWithMe.override_enabled(true);
|
||||
App::test(Assets, |mut app| async move {
|
||||
App::test(ASSETS, |mut app| async move {
|
||||
initialize_app(&mut app);
|
||||
let mut server_api = mock_server_api();
|
||||
|
||||
Reference in New Issue
Block a user