Files
openobserve/web/src/services/jstransform.ts
T
Subhra264 36860c7a59 fix: allow replacing the failed enrichment table url (#9958)
### **User description**
If there are multiple successful urls added for an enrichment table, but
the last append was failed, user now can replace the failed url with a
new one to rectify if any url issue is there.


___

### **PR Type**
Bug fix, Enhancement


___

### **Description**
- Add `replace_failed` flag to enrichment table API

- Backend: allow replacing only failed job URL

- UI: new Replace Failed URL update mode

- Adjust client and handler logic for replace_failed


___

### Diagram Walkthrough


```mermaid
flowchart LR
  UI["Vue UI"] -->|select replace_failed| Client["jstransform Service"]
  Client -->|POST replace_failed| API["Request Handler"]
  API -->|replace_failed| ProcessFailed["Replace Failed Job"]
  API -->|append & has_failed| RejectAppend["Reject Append Request"]
  API -->|retry| RetryAll["Retry All Jobs"]
  API -->|else| ReplaceAll["Replace All Jobs"]
```



<details> <summary><h3> File Walkthrough</h3></summary>

<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>jstransform.ts</strong><dd><code>Add replace_failed to
API client method</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

web/src/services/jstransform.ts

<ul><li>Added <code>replace_failed</code> parameter to method
signature<br> <li> Included <code>replace_failed</code> in POST request
body</ul>


</details>


  </td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9958/files#diff-301add2528e0f32323ca4c503bd7d460ab15ca6b9a9537192a02c5e52fd82926">+2/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>mod.rs</strong><dd><code>Support replace_failed logic
in handler</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

src/handler/http/request/enrichment_table/mod.rs

<ul><li>Added <code>replace_failed</code> field with serde default<br>
<li> Extracted <code>replace_failed</code> from request body<br> <li>
Updated append validation to allow replace_failed<br> <li> Added branch
for replacing only failed job URL</ul>


</details>


  </td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9958/files#diff-7b5b203002d1c3e5f671392a2a8ed84f45225896b652c2dac94ac26e72a43124">+49/-4</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>AddEnrichmentTable.vue</strong><dd><code>UI for Replace
Failed URL mode</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

web/src/components/functions/AddEnrichmentTable.vue

<ul><li>Added replace_failed updateMode option and styling<br> <li>
Conditional URL input for replace_failed mode<br> <li> Computed
<code>hasFailedJob</code> and <code>updateModeOptions</code><br> <li>
Forwarded <code>replaceFailedFlag</code> in service call</ul>


</details>


  </td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9958/files#diff-9aad551dbc051edfdb3994a664506ed6d5e27dcb64f9c2fa917b02e51a35d86e">+42/-10</a>&nbsp;
</td>

</tr>
</table></td></tr></tr></tbody></table>

</details>

___
2026-01-12 13:18:16 +05:30

139 lines
4.3 KiB
TypeScript

// Copyright 2023 OpenObserve Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import http from "./http";
import { TestFunctionPayload } from "@/ts/interfaces/function";
const jstransform = {
list: (
page_num: number,
page_size: number,
sort_by: string,
desc: boolean,
name: string,
org_identifier: string,
) => {
return http().get(
`/api/${org_identifier}/functions?page_num=${page_num}&page_size=${page_size}&sort_by=${sort_by}&desc=${desc}&name=${name}`,
);
},
create: (org_identifier: string, data: any) => {
return http().post(`/api/${org_identifier}/functions`, data);
},
getAssociatedPipelines: (org_identifier: string, name: string) => {
return http().get(`/api/${org_identifier}/functions/${name}`);
},
update: (org_identifier: string, data: any) => {
return http().put(`/api/${org_identifier}/functions/${data.name}`, data);
},
delete: (org_identifier: string, transform_name: string, force?: boolean) => {
const url = `/api/${org_identifier}/functions/${transform_name}`;
const config = force ? { params: { force: true } } : {};
return http().delete(url, config);
},
bulkDelete: (org_identifier: string, data: any) => {
return http().delete(`/api/${org_identifier}/functions/bulk`, { data });
},
create_with_index: (
org_identifier: string,
stream_name: string,
stream_type: string,
data: any,
) => {
return http().put(
`/api/${org_identifier}/${stream_name}/functions/${data.name}?type=${stream_type}`,
data,
);
},
delete_stream_function: (
org_identifier: string,
stream_name: string,
stream_type: string,
transform_name: string,
) => {
return http().delete(
`/api/${org_identifier}/${stream_name}/functions/${transform_name}?type=${stream_type}`,
);
},
stream_function: (
org_identifier: string,
stream_name: string,
stream_type: string,
) => {
return http().get(
`/api/${org_identifier}/streams/${stream_name}/functions?type=${stream_type}`,
);
},
apply_stream_function: (
org_identifier: string,
stream_name: string,
stream_type: string,
function_name: string,
data: any,
) => {
return http().put(
`/api/${org_identifier}/streams/${stream_name}/functions/${function_name}?type=${stream_type}`,
data,
);
},
remove_stream_function: (
org_identifier: string,
stream_name: string,
stream_type: string,
function_name: string,
) => {
return http().delete(
`/api/${org_identifier}/streams/${stream_name}/functions/${function_name}?type=${stream_type}`,
);
},
create_enrichment_table: (
org_identifier: string,
table_name: string,
data: any,
append: boolean,
) => {
return http({ headers: { "Content-Type": "multipart/form-data" } }).post(
`/api/${org_identifier}/enrichment_tables/${table_name}?append=${append}`,
data,
);
},
create_enrichment_table_from_url: (
org_identifier: string,
table_name: string,
url: string,
append_data: boolean,
resume: boolean = false,
retry: boolean = false,
replace_failed: boolean = false,
) => {
return http().post(
`/api/${org_identifier}/enrichment_tables/${table_name}/url?append=${append_data}&resume=${resume}&retry=${retry}`,
{ url, replace_failed },
);
},
get_all_enrichment_table_statuses: (
org_identifier: string,
) => {
return http().get(
`/api/${org_identifier}/enrichment_tables/status`,
);
},
test: (org_identifier: string, data: TestFunctionPayload) => {
return http().post(`/api/${org_identifier}/functions/test`, data);
},
};
export default jstransform;