Skip to content

Conversation

@Junjiequan
Copy link
Member

Description

Motivation

Fixes

  • Bug fixed (#X)

Changes:

  • changes made

Tests included

  • Included for each change/fix?
  • Passing?

Documentation

  • swagger documentation updated (required for API changes)
  • official documentation updated

official documentation info

@Junjiequan Junjiequan requested a review from a team as a code owner November 17, 2025 15:36
@Junjiequan Junjiequan marked this pull request as draft November 17, 2025 15:36
@Junjiequan Junjiequan added the ESS label Nov 18, 2025
@Junjiequan Junjiequan changed the title Swap 5086 scicat be poc store frontend config into the data feat: add run time config management service Nov 18, 2025
@Junjiequan Junjiequan marked this pull request as ready for review November 18, 2025 16:18
@Junjiequan Junjiequan force-pushed the SWAP-5086-scicat-be-poc-store-frontend-config-into-the-data branch from e8b20cd to 26bb728 Compare November 18, 2025 16:18
@Junjiequan Junjiequan self-assigned this Nov 18, 2025
@Junjiequan Junjiequan force-pushed the SWAP-5086-scicat-be-poc-store-frontend-config-into-the-data branch from 6a92f73 to e7e05c5 Compare November 21, 2025 12:21
@sbliven
Copy link
Member

sbliven commented Nov 25, 2025

@Junjiequan Can you add an example for how to use this?

@Junjiequan Junjiequan changed the title feat: add run time config management service feat(POC): add run time config management service Nov 25, 2025
Copy link
Contributor

@bpedersen2 bpedersen2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound good in general.

I guess a filter for certain fields will be needed in the end if we allow be-config changes, e.g. to avoid loss of all admin groups or changes to mongodb settings( I would probably keep all security-related fields as file-only).

Frontend-config should be less critical.

Copy link
Member

@sbliven sbliven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should discuss the core premise of this POC, which is that the configuration should be stored in the database instead of in files. While it would be convenient to be able to change the configuration on the fly, I'm worried that it will become even harder to track configuration changes. If we do it, I think there should be a clear process to "burn in" the configuration: export non-default settings to an env file, empty the database, and restart the backend with a clean configuration. Otherwise it's hard to keep track of changes.

Can you add a description of the usage to the README or docs? Even if it changes later, it would be helpful to read how the merging works. I think you said that the database is considered canon and overrides anything in the config files or the defaults.

How does this fit with /admin/config? Would this provide the merged "frontend" data?

Likewise, will calls to the configService be merged to the "backend" data? If so, we should double-check that there aren't any remaining direct calls to configuration(), as those would bypass the configService.

I guess you would add more endpoints

  • get the full, merged configuration
  • get/set individual properties (or would this just be done with PATCH application/json+merge?)
  • way to delete configuration changes (resetting from the files or defaults)

export class RuntimeConfigController {
constructor(private readonly runtimeConfigService: RuntimeConfigService) {}

@AllowAny()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs the swagger descriptors (ApiOperation, ApiParam, etc)

example: "frontend",
})
@IsString()
_id: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest key for the unique identifier. _id should only be used for the internal mongo document id (which should not be accessible in the API).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to have more than "frontend" and "backend"? I would make this an enum. Or are you thinking there might be use cases where other microservices store most of their configs on the scicat backend?

Copy link
Member Author

@Junjiequan Junjiequan Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_id should only be used for the internal mongo document id (which should not be accessible in the API).

I'm not sure about this statement.
await this.datablocksService.findOne({ where: { _id: id }, }); we have been implementing query like this in many places, I don't see what's the cons here..

Does it make sense to have more than "frontend" and "backend"? I would make this an enum. Or are you thinking there might be use cases where other microservices store most of their configs on the scicat backend?

We don’t want to lock it to just “frontend” or “backend”.
The idea is to let operators store any JSON config they want, and the backend shouldnt restrict it. They decide what config files they want to use, not us. It could be frontend-config, published-data-schema.json, proposal-ui-config etc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest just id as we ill store the whole configuration in one document... or at least, that was the idea last time we brainstormed.

})
@IsOptional()
@IsString()
description?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the use of this? Just internal documentation?

Copy link
Member

@nitrosx nitrosx Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the idea.
If a site admin uses this subsystem to store additional configurations, we should also have a name and a description for management purposes.

@@ -0,0 +1,42 @@
export const isPlainObject = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use common.utils.IsRecord()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

constructor(private readonly runtimeConfigService: RuntimeConfigService) {}

@AllowAny()
@Get("data/:id")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data strikes me as a surprising choice for the endpoint path. I see a close link between this functionality and the /admin/config endpoint. Maybe it could just be GET/PUT/PATCH /admin/config/:id? And there should be a way to get either the merged configuration or just the overridden values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not remember why we decided to move it away from admin/config.
If I remember correctly, the reason for it is that this subsystem can become a store for additional blobs besides configurations. In our mind admin/config relates only to admin users, which is true for updating but not for retrieving.
Hopefully it makes sense, but I will be happy to discuss further

@Junjiequan
Copy link
Member Author

Junjiequan commented Nov 27, 2025

I think we should discuss the core premise of this POC, which is that the configuration should be stored in the database instead of in files. While it would be convenient to be able to change the configuration on the fly, I'm worried that it will become even harder to track configuration changes. If we do it, I think there should be a clear process to "burn in" the configuration: export non-default settings to an env file, empty the database, and restart the backend with a clean configuration. Otherwise it's hard to keep track of changes.

We defintelly needs to discuss more about this, I just wanted to pull the idea into code, so we can have something to disccuss upon.

If i understand your proposal correctly, you are suggesting that:

  1. the backend always starts with a empty config collection
  2. it then loads the config files from disk (mounted or default)
  3. creates a fresh config record based on provided files

So, the config file is the source of truth, config record is temporary copy for real time editing. once the backend restarts the temporary state resets and rebuilt from the file again.

Is it correct intepretation?

Can you add a description of the usage to the README or docs? Even if it changes later, it would be helpful to read how the merging works. I think you said that the database is considered canon and overrides anything in the config files or the defaults.

Sure, I will provide it as soon as possible.

How does this fit with /admin/config? Would this provide the merged "frontend" data?

It's up for discussion that wheter if we still want to keep /admin/config after we have the runtimeConfig endpoint.

Likewise, will calls to the configService be merged to the "backend" data? If so, we should double-check that there aren't any remaining direct calls to configuration(), as those would bypass the configService.

The backend data ( environment variables I assume ) is completly seperated logic and should not be relevant to the run time config service at all, they are out of scope this time at least. The run time service serves for frontend related configs only.

I guess you would add more endpoints

get the full, merged configuration
get/set individual properties (or would this just be done with PATCH application/json+merge?)
way to delete configuration changes (resetting from the files or defaults)

I imagine the entry sturcture will look like this:

[
  {
    "_id": "frontendConfig",
    "description": "Some text to be rendered on the UI",
    "data": {
      "...": "raw JSON blob"
    }
  },
  {
    "_id": "frontendTheme",
    "data": {
      "...": "raw JSON blob"
    }
  },
  {
    "_id": "someOtherConfig",
    "data": {
      "...": "raw JSON blob"
    }
  }
]

On the frontend we use jsonforms, which always submits the full JSON object. So, I’m not sure individual property endpoints add much value right now. JSONForms doesn’t send partial updates, so we’d essentially be duplicating logic.
For now, setting/getting the whole config blob seems enough, unless we decide to go with other json editors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also the fields createdBy, updatedAt, createdAt.

constructor(private readonly runtimeConfigService: RuntimeConfigService) {}

@AllowAny()
@Get("data/:id")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not remember why we decided to move it away from admin/config.
If I remember correctly, the reason for it is that this subsystem can become a store for additional blobs besides configurations. In our mind admin/config relates only to admin users, which is true for updating but not for retrieving.
Hopefully it makes sense, but I will be happy to discuss further

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming is perfect if we are going to use this subsystem to store only configurations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as my previous comment

@@ -0,0 +1,42 @@
export const isPlainObject = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

@nitrosx
Copy link
Member

nitrosx commented Nov 27, 2025

@sbliven valid feedback!!!
Let me and Jay brainstorm once or twice more and get back to you.
We can discuss afterwards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants