Skip to content

Commit 8e53243

Browse files
committed
feat: add kubernetes app role selection
Signed-off-by: Anupam Kumar <kyteinsky@gmail.com>
1 parent cbca6e8 commit 8e53243

5 files changed

Lines changed: 46 additions & 8 deletions

File tree

appinfo/info.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,19 @@ Setup background job workers as described here: https://docs.nextcloud.com/serve
8282
<description>Password to be used for authenticating requests to the OpenAI-compatible endpoint set in CC_EM_BASE_URL.</description>
8383
</variable>
8484
</environment-variables>
85+
<k8s-service-roles>
86+
<role>
87+
<name>rp</name>
88+
<display-name>Request Processing Mode</display-name>
89+
<env>APP_ROLE=rp</env>
90+
<expose>true</expose>
91+
</role>
92+
<role>
93+
<name>indexing</name>
94+
<display-name>Indexing Mode</display-name>
95+
<env>APP_ROLE=indexing</env>
96+
<expose>false</expose>
97+
</role>
98+
</k8s-service-roles>
8599
</external-app>
86100
</info>

context_chat_backend/controller.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
def enabled_handler(enabled: bool, _: NextcloudApp | AsyncNextcloudApp) -> str:
7676
if enabled:
7777
app_enabled.set()
78+
# todo: start bg threads to fetch docs, updates and requests to process
7879
else:
7980
app_enabled.clear()
8081

@@ -213,6 +214,13 @@ def _():
213214
return JSONResponse(content={'enabled': app_enabled.is_set()}, status_code=200)
214215

215216

217+
@app.post('/countIndexedDocuments')
218+
@enabled_guard(app)
219+
def _():
220+
counts = exec_in_proc(target=count_documents_by_provider, args=(vectordb_loader,))
221+
return JSONResponse(counts)
222+
223+
216224
@app.post('/updateAccessDeclarative')
217225
@enabled_guard(app)
218226
def _(
@@ -328,13 +336,6 @@ def _(userId: str = Body(embed=True)):
328336
return JSONResponse('User deleted')
329337

330338

331-
@app.post('/countIndexedDocuments')
332-
@enabled_guard(app)
333-
def _():
334-
counts = exec_in_proc(target=count_documents_by_provider, args=(vectordb_loader,))
335-
return JSONResponse(counts)
336-
337-
338339
@app.put('/loadSources')
339340
@enabled_guard(app)
340341
def _(sources: list[UploadFile]):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#
2+
# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
#

context_chat_backend/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
33
# SPDX-License-Identifier: AGPL-3.0-or-later
44
#
5+
from enum import Enum
6+
57
from pydantic import BaseModel
68

79
__all__ = [
@@ -71,3 +73,9 @@ class FatalEmbeddingException(EmbeddingException):
7173
7274
Either malformed request, authentication error, or other non-retryable error.
7375
"""
76+
77+
78+
class AppRole(str, Enum):
79+
NORMAL = 'normal'
80+
INDEXING = 'indexing'
81+
RP = 'rp'

context_chat_backend/utils.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#
55
import logging
66
import multiprocessing as mp
7+
import os
78
import re
89
import traceback
910
from collections.abc import Callable
@@ -14,7 +15,7 @@
1415

1516
from fastapi.responses import JSONResponse as FastAPIJSONResponse
1617

17-
from .types import TConfig, TEmbeddingAuthApiKey, TEmbeddingAuthBasic, TEmbeddingConfig
18+
from .types import AppRole, TConfig, TEmbeddingAuthApiKey, TEmbeddingAuthBasic, TEmbeddingConfig
1819

1920
T = TypeVar('T')
2021
_logger = logging.getLogger('ccb.utils')
@@ -144,3 +145,13 @@ def redact_config(config: TConfig | TEmbeddingConfig) -> TConfig | TEmbeddingCon
144145
em_conf.auth.password = '***REDACTED***' # noqa: S105
145146

146147
return config_copy
148+
149+
150+
def get_app_role() -> AppRole:
151+
role = os.getenv('APP_ROLE', '').lower()
152+
if role == '':
153+
return AppRole.NORMAL
154+
if role not in ['indexing', 'rp']:
155+
_logger.warning(f'Invalid app role: {role}, defaulting to all roles')
156+
return AppRole.NORMAL
157+
return AppRole(role)

0 commit comments

Comments
 (0)