Skip to content

Commit

Permalink
Merge branch 'disable-ws' into 'main'
Browse files Browse the repository at this point in the history
Add setting to disable websockets

See merge request reportcreator/reportcreator!631
  • Loading branch information
MWedl committed Jul 30, 2024
2 parents fd5c619 + 2d61703 commit 4865130
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next
* Set restart policy for redis docker container
* Add setting to disable websockets and always use HTTP for collaborative editing
* Fix error while sorting finding templates by created/updated date
* Fix create template from finding changes not saved

Expand Down
1 change: 1 addition & 0 deletions api/src/reportcreator_api/api_utils/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def settings_endpoint(self, *args, **kwargs):
'archiving': license.is_professional(),
'permissions': license.is_professional(),
'backup': bool(settings.BACKUP_KEY and license.is_professional()),
'websockets': not settings.DISABLE_WEBSOCKETS,
},
'guest_permissions': {
'import_projects': settings.GUEST_USERS_CAN_IMPORT_PROJECTS,
Expand Down
3 changes: 2 additions & 1 deletion api/src/reportcreator_api/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@

# Websockets
REDIS_URL = config('REDIS_URL', default=None)
if REDIS_URL:
DISABLE_WEBSOCKETS = config('DISABLE_WEBSOCKETS', cast=bool, default=False) or (not REDIS_URL)
if not DISABLE_WEBSOCKETS:
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
Expand Down
10 changes: 10 additions & 0 deletions docs/docs/setup/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,13 @@ This flag also enables setting the `Secure` flag for cookies.
```
SECURE_SSL_REDIRECT=on
```


### WebSockets
Disable WebSockets and always use HTTP fallback for collaborative editing.
This is not recommended because some features are only available with WebSockets and HTTP fallback has higher latency.
This setting sould only be activated if WebSockets are blocked by a firewall or not supported by a reverse proxy.

``` title="Example:"
DISABLE_WEBSOCKETS=true
```
6 changes: 4 additions & 2 deletions frontend/src/components/CollabLoader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<slot />

<v-snackbar
v-if="!isFirstLoad"
v-if="!isFirstLoad && (props.collab.connection?.value?.connectionAttempt || 0) > 0"
:model-value="connectionState !== CollabConnectionState.OPEN"
timeout="-1"
color="warning"
Expand Down Expand Up @@ -36,6 +36,8 @@ defineOptions({
inheritAttrs: false
});
const apiSettings = useApiSettings();
const props = defineProps<{
collab: {
connection: ComputedRef<CollabConnectionInfo|undefined>;
Expand All @@ -53,7 +55,7 @@ watch(connectionState, async (newState, oldState) => {
reconnectAttempted.value = 0;
// Show warning if HTTP fallback was used
if (props.collab.connection.value?.type === CollabConnectionType.HTTP_FALLBACK && !warningHttpFallbackShown.value) {
if (apiSettings.settings!.features.websockets && props.collab.connection.value?.type === CollabConnectionType.HTTP_FALLBACK && !warningHttpFallbackShown.value) {
warningHttpFallbackShown.value = true;
warningToast('Could not establish WebSocket connection, falling back to HTTP. Some features may be limited.');
}
Expand Down
22 changes: 15 additions & 7 deletions frontend/src/utils/collab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export type CollabConnectionInfo = {
type: CollabConnectionType;
connectionState: CollabConnectionState;
connectionError?: { error: any, message?: string };
connectionAttempt?: number;
connect: () => Promise<void>;
disconnect: () => Promise<void>;
send: (msg: CollabEvent) => void;
Expand Down Expand Up @@ -492,6 +493,7 @@ export function connectionHttpReadonly<T = any>(storeState: CollabStoreState<T>,
}

export function useCollab<T = any>(storeState: CollabStoreState<T>) {
const apiSettings = useApiSettings();
const eventBusBeforeApplyRemoteTextChange = useEventBus('collab:beforeApplyRemoteTextChanges');
const eventBusBeforeApplySetValue = useEventBus('collab:beforeApplySetValue');

Expand Down Expand Up @@ -530,19 +532,25 @@ export function useCollab<T = any>(storeState: CollabStoreState<T>) {
storeState.connection = {
type: CollabConnectionType.WEBSOCKET,
connectionState: CollabConnectionState.CONNECTING,
connectionAttempt: 0,
connect: () => Promise.resolve(),
disconnect: () => Promise.resolve(),
send: () => {},
};

// Try websocket connection first
for (let i = 0; i < 2; i++) {
try {
return await connectTo(connectionWebsocket(storeState, onReceiveMessage));
} catch {
// Backoff time for reconnecting
if (i === 0) {
await new Promise(resolve => setTimeout(resolve, 500));
if (apiSettings.settings!.features.websockets) {
for (let i = 0; i < 2; i++) {
try {
return await connectTo(connectionWebsocket(storeState, onReceiveMessage));
} catch {
// Increment reconnection attempt counter
storeState.connection!.connectionAttempt = (storeState.connection!.connectionAttempt || 0) + 1;

// Backoff time for reconnecting
if (i === 0) {
await new Promise(resolve => setTimeout(resolve, 500));
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export type ApiSettings = {
readonly archiving: boolean;
readonly permissions: boolean;
readonly backup: boolean;
readonly websockets: boolean;
};
readonly guest_permissions: {
readonly import_projects: boolean;
Expand Down

0 comments on commit 4865130

Please sign in to comment.