[] {
return [
{
accessorKey: 'timestamp',
diff --git a/frontend/apps/web/app/(mgmt)/[account]/runs/[id]/page.tsx b/frontend/apps/web/app/(mgmt)/[account]/runs/[id]/page.tsx
index a19b269514..09ae84f3e4 100644
--- a/frontend/apps/web/app/(mgmt)/[account]/runs/[id]/page.tsx
+++ b/frontend/apps/web/app/(mgmt)/[account]/runs/[id]/page.tsx
@@ -72,6 +72,7 @@ export default function Page({ params }: PageProps): ReactElement {
}
);
const jobRun = data?.jobRun;
+ jobRun?.status;
const {
data: eventData,
@@ -351,7 +352,14 @@ export default function Page({ params }: PageProps): ReactElement {
{!isSystemAppConfigDataLoading &&
systemAppConfigData?.enableRunLogs && (
-
+
)}
diff --git a/frontend/apps/web/app/api/accounts/[accountId]/runs/[id]/logs/route.ts b/frontend/apps/web/app/api/accounts/[accountId]/runs/[id]/logs/route.ts
deleted file mode 100644
index bc2c05bd71..0000000000
--- a/frontend/apps/web/app/api/accounts/[accountId]/runs/[id]/logs/route.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { withNeosyncContext } from '@/api-only/neosync-context';
-import { RequestContext } from '@/shared';
-import { create } from '@bufbuild/protobuf';
-import {
- GetJobRunLogsStreamRequestSchema,
- GetJobRunLogsStreamResponse,
- LogLevel,
- LogWindow,
-} from '@neosync/sdk';
-import { NextRequest, NextResponse } from 'next/server';
-
-export async function GET(
- req: NextRequest,
- { params }: RequestContext
-): Promise {
- return withNeosyncContext(async (ctx) => {
- const { searchParams } = new URL(req.url);
- const loglevel = searchParams.get('loglevel');
- const response = ctx.client.jobs.getJobRunLogsStream(
- create(GetJobRunLogsStreamRequestSchema, {
- jobRunId: params.id,
- accountId: params.accountId,
- window: getWindow('1d'),
- shouldTail: false,
- maxLogLines: BigInt('5000'),
- logLevels: [loglevel ? parseInt(loglevel, 10) : LogLevel.UNSPECIFIED],
- })
- );
- const logs: GetJobRunLogsStreamResponse[] = [];
- for await (const logRes of response) {
- logs.push(logRes);
- }
- return logs;
- })(req);
-}
-
-function getWindow(window?: string): LogWindow {
- if (!window) {
- return LogWindow.NO_TIME_UNSPECIFIED;
- }
- if (window === '15m' || window === '15min') {
- return LogWindow.FIFTEEN_MIN;
- }
- if (window === '1h') {
- return LogWindow.ONE_HOUR;
- }
- if (window === '1d') {
- return LogWindow.ONE_DAY;
- }
- return LogWindow.NO_TIME_UNSPECIFIED;
-}
diff --git a/frontend/apps/web/libs/hooks/useGetJobRunLogs.ts b/frontend/apps/web/libs/hooks/useGetJobRunLogs.ts
deleted file mode 100644
index bf037e2ff7..0000000000
--- a/frontend/apps/web/libs/hooks/useGetJobRunLogs.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { fromJson, isMessage } from '@bufbuild/protobuf';
-import {
- GetJobRunLogsStreamResponse,
- GetJobRunLogsStreamResponseSchema,
- LogLevel,
-} from '@neosync/sdk';
-import { useQuery, UseQueryResult } from '@tanstack/react-query';
-import { fetcher } from '../fetcher';
-
-interface GetJobRunLogsOptions {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- refreshIntervalFn?(data: any): number;
-}
-
-export function useGetJobRunLogs(
- runId: string,
- accountId: string,
- loglevel: LogLevel,
- opts: GetJobRunLogsOptions = {}
-): UseQueryResult {
- const { refreshIntervalFn } = opts;
- const query = new URLSearchParams({
- loglevel: loglevel.toString(),
- });
- return useQuery({
- queryKey: [
- '/api/accounts',
- accountId,
- 'runs',
- runId,
- 'logs',
- '?',
- query.toString(),
- ],
- queryFn: (ctx) => fetcher(ctx.queryKey.join('/')),
- refetchInterval(query) {
- return query.state.data && refreshIntervalFn
- ? refreshIntervalFn(query.state.data)
- : 0;
- },
- select(data) {
- const dataArr = Array.isArray(data) ? data : [data];
- return dataArr.map((d) =>
- isMessage(GetJobRunLogsStreamResponseSchema, d)
- ? d
- : fromJson(GetJobRunLogsStreamResponseSchema, d)
- );
- },
- enabled: !!runId && !!accountId && !!loglevel,
- });
-}
-
-const TEN_SECONDS = 5 * 1000;
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export function refreshLogsWhenRunNotComplete(data: any): number {
- const dataArr = Array.isArray(data) ? data : [data];
- return dataArr.some((d) => {
- const converted: GetJobRunLogsStreamResponse = isMessage(
- GetJobRunLogsStreamResponseSchema,
- d
- )
- ? d
- : fromJson(GetJobRunLogsStreamResponseSchema, d);
- return (
- converted.logLine.includes('context canceled') ||
- converted.logLine.includes('workflow completed')
- );
- })
- ? 0
- : TEN_SECONDS;
-}
diff --git a/frontend/apps/web/shared/index.ts b/frontend/apps/web/shared/index.ts
deleted file mode 100644
index fcb073fefc..0000000000
--- a/frontend/apps/web/shared/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './types';
diff --git a/frontend/apps/web/shared/types.ts b/frontend/apps/web/shared/types.ts
deleted file mode 100644
index 27ba8d9f66..0000000000
--- a/frontend/apps/web/shared/types.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Second parameter for an API Route.
- * ```ts
- * function GET(req: NextRequest, reqCtx: RequestContext): Promise
- * ```
- */
-export interface RequestContext {
- params: Record;
-}
diff --git a/frontend/packages/sdk/src/client/mgmt/v1alpha1/job_pb.ts b/frontend/packages/sdk/src/client/mgmt/v1alpha1/job_pb.ts
index f516418010..2ca2c1939f 100644
--- a/frontend/packages/sdk/src/client/mgmt/v1alpha1/job_pb.ts
+++ b/frontend/packages/sdk/src/client/mgmt/v1alpha1/job_pb.ts
@@ -15,7 +15,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file mgmt/v1alpha1/job.proto.
*/
export const file_mgmt_v1alpha1_job: GenFile = /*@__PURE__*/
- fileDesc("ChdtZ210L3YxYWxwaGExL2pvYi5wcm90bxINbWdtdC52MWFscGhhMSIuCg5HZXRKb2JzUmVxdWVzdBIcCgphY2NvdW50X2lkGAEgASgJQgi6SAVyA7ABASIzCg9HZXRKb2JzUmVzcG9uc2USIAoEam9icxgBIAMoCzISLm1nbXQudjFhbHBoYTEuSm9iIkUKCUpvYlNvdXJjZRI4CgdvcHRpb25zGAEgASgLMh8ubWdtdC52MWFscGhhMS5Kb2JTb3VyY2VPcHRpb25zQga6SAPIAQEioQQKEEpvYlNvdXJjZU9wdGlvbnMSQgoIcG9zdGdyZXMYASABKAsyLi5tZ210LnYxYWxwaGExLlBvc3RncmVzU291cmNlQ29ubmVjdGlvbk9wdGlvbnNIABI9CgZhd3NfczMYAiABKAsyKy5tZ210LnYxYWxwaGExLkF3c1MzU291cmNlQ29ubmVjdGlvbk9wdGlvbnNIABI8CgVteXNxbBgDIAEoCzIrLm1nbXQudjFhbHBoYTEuTXlzcWxTb3VyY2VDb25uZWN0aW9uT3B0aW9uc0gAEjgKCGdlbmVyYXRlGAQgASgLMiQubWdtdC52MWFscGhhMS5HZW5lcmF0ZVNvdXJjZU9wdGlvbnNIABI9CgthaV9nZW5lcmF0ZRgFIAEoCzImLm1nbXQudjFhbHBoYTEuQWlHZW5lcmF0ZVNvdXJjZU9wdGlvbnNIABJACgdtb25nb2RiGAYgASgLMi0ubWdtdC52MWFscGhhMS5Nb25nb0RCU291cmNlQ29ubmVjdGlvbk9wdGlvbnNIABJCCghkeW5hbW9kYhgHIAEoCzIuLm1nbXQudjFhbHBoYTEuRHluYW1vREJTb3VyY2VDb25uZWN0aW9uT3B0aW9uc0gAEjwKBW1zc3FsGAggASgLMisubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zSABCDwoGY29uZmlnEgW6SAIIASJuChRDcmVhdGVKb2JEZXN0aW5hdGlvbhIfCg1jb25uZWN0aW9uX2lkGAEgASgJQgi6SAVyA7ABARI1CgdvcHRpb25zGAIgASgLMiQubWdtdC52MWFscGhhMS5Kb2JEZXN0aW5hdGlvbk9wdGlvbnMidAoOSm9iRGVzdGluYXRpb24SHwoNY29ubmVjdGlvbl9pZBgBIAEoCUIIukgFcgOwAQESNQoHb3B0aW9ucxgCIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iRGVzdGluYXRpb25PcHRpb25zEgoKAmlkGAMgASgJIt0CChdBaUdlbmVyYXRlU291cmNlT3B0aW9ucxIiChBhaV9jb25uZWN0aW9uX2lkGAEgASgJQgi6SAVyA7ABARJGCgdzY2hlbWFzGAIgAygLMisubWdtdC52MWFscGhhMS5BaUdlbmVyYXRlU291cmNlU2NoZW1hT3B0aW9uQgi6SAWSAQIIARIuChdma19zb3VyY2VfY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQFIAIgBARIbCgptb2RlbF9uYW1lGAQgASgJQge6SARyAhABEhgKC3VzZXJfcHJvbXB0GAUgASgJSAGIAQESKwoTZ2VuZXJhdGVfYmF0Y2hfc2l6ZRgGIAEoA0IJukgGIgQYZCgBSAKIAQFCGgoYX2ZrX3NvdXJjZV9jb25uZWN0aW9uX2lkQg4KDF91c2VyX3Byb21wdEIWChRfZ2VuZXJhdGVfYmF0Y2hfc2l6ZSJ9ChxBaUdlbmVyYXRlU291cmNlU2NoZW1hT3B0aW9uEhcKBnNjaGVtYRgBIAEoCUIHukgEcgIQARJECgZ0YWJsZXMYAiADKAsyKi5tZ210LnYxYWxwaGExLkFpR2VuZXJhdGVTb3VyY2VUYWJsZU9wdGlvbkIIukgFkgECCAEiVAobQWlHZW5lcmF0ZVNvdXJjZVRhYmxlT3B0aW9uEhYKBXRhYmxlGAEgASgJQge6SARyAhABEh0KCXJvd19jb3VudBgCIAEoA0IKukgHIgUY6AcoASKvAQoVR2VuZXJhdGVTb3VyY2VPcHRpb25zEkQKB3NjaGVtYXMYASADKAsyKS5tZ210LnYxYWxwaGExLkdlbmVyYXRlU291cmNlU2NoZW1hT3B0aW9uQgi6SAWSAQIIARIuChdma19zb3VyY2VfY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQFIAIgBAUIaChhfZmtfc291cmNlX2Nvbm5lY3Rpb25faWRKBAgCEAMieQoaR2VuZXJhdGVTb3VyY2VTY2hlbWFPcHRpb24SFwoGc2NoZW1hGAEgASgJQge6SARyAhABEkIKBnRhYmxlcxgCIAMoCzIoLm1nbXQudjFhbHBoYTEuR2VuZXJhdGVTb3VyY2VUYWJsZU9wdGlvbkIIukgFkgECCAEiTwoZR2VuZXJhdGVTb3VyY2VUYWJsZU9wdGlvbhIWCgV0YWJsZRgBIAEoCUIHukgEcgIQARIaCglyb3dfY291bnQYAiABKANCB7pIBCICKAEiQQoeTW9uZ29EQlNvdXJjZUNvbm5lY3Rpb25PcHRpb25zEh8KDWNvbm5lY3Rpb25faWQYASABKAlCCLpIBXIDsAEBIu8BCh9EeW5hbW9EQlNvdXJjZUNvbm5lY3Rpb25PcHRpb25zEh8KDWNvbm5lY3Rpb25faWQYASABKAlCCLpIBXIDsAEBEjgKBnRhYmxlcxgCIAMoCzIoLm1nbXQudjFhbHBoYTEuRHluYW1vREJTb3VyY2VUYWJsZU9wdGlvbhJRChN1bm1hcHBlZF90cmFuc2Zvcm1zGAMgASgLMjQubWdtdC52MWFscGhhMS5EeW5hbW9EQlNvdXJjZVVubWFwcGVkVHJhbnNmb3JtQ29uZmlnEh4KFmVuYWJsZV9jb25zaXN0ZW50X3JlYWQYBCABKAgi/QEKJUR5bmFtb0RCU291cmNlVW5tYXBwZWRUcmFuc2Zvcm1Db25maWcSLwoBYhgBIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iTWFwcGluZ1RyYW5zZm9ybWVyEjUKB2Jvb2xlYW4YAiABKAsyJC5tZ210LnYxYWxwaGExLkpvYk1hcHBpbmdUcmFuc2Zvcm1lchIvCgFuGAQgASgLMiQubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nVHJhbnNmb3JtZXISLwoBcxgGIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iTWFwcGluZ1RyYW5zZm9ybWVySgQIAxAESgQIBRAGIl8KGUR5bmFtb0RCU291cmNlVGFibGVPcHRpb24SFgoFdGFibGUYASABKAlCB7pIBHICEAESGQoMd2hlcmVfY2xhdXNlGAIgASgJSACIAQFCDwoNX3doZXJlX2NsYXVzZSKeBwofUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucxI6CgdzY2hlbWFzGAIgAygLMikubWdtdC52MWFscGhhMS5Qb3N0Z3Jlc1NvdXJjZVNjaGVtYU9wdGlvbhIfCg1jb25uZWN0aW9uX2lkGAMgASgJQgi6SAVyA7ABARIpCiFzdWJzZXRfYnlfZm9yZWlnbl9rZXlfY29uc3RyYWludHMYBCABKAgSbgocbmV3X2NvbHVtbl9hZGRpdGlvbl9zdHJhdGVneRgFIAEoCzJILm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5OZXdDb2x1bW5BZGRpdGlvblN0cmF0ZWd5EmUKF2NvbHVtbl9yZW1vdmFsX3N0cmF0ZWd5GAYgASgLMkQubWdtdC52MWFscGhhMS5Qb3N0Z3Jlc1NvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneRqJAgoZTmV3Q29sdW1uQWRkaXRpb25TdHJhdGVneRJkCghoYWx0X2pvYhgBIAEoCzJQLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5OZXdDb2x1bW5BZGRpdGlvblN0cmF0ZWd5LkhhbHRKb2JIABJkCghhdXRvX21hcBgCIAEoCzJQLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5OZXdDb2x1bW5BZGRpdGlvblN0cmF0ZWd5LkF1dG9NYXBIABoJCgdIYWx0Sm9iGgkKB0F1dG9NYXBCCgoIc3RyYXRlZ3kaiQIKFUNvbHVtblJlbW92YWxTdHJhdGVneRJgCghoYWx0X2pvYhgBIAEoCzJMLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5Db2x1bW5SZW1vdmFsU3RyYXRlZ3kuSGFsdEpvYkgAEmgKDGNvbnRpbnVlX2pvYhgCIAEoCzJQLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5Db2x1bW5SZW1vdmFsU3RyYXRlZ3kuQ29udGludWVKb2JIABoJCgdIYWx0Sm9iGg0KC0NvbnRpbnVlSm9iQgoKCHN0cmF0ZWd5SgQIARACInkKGlBvc3RncmVzU291cmNlU2NoZW1hT3B0aW9uEhcKBnNjaGVtYRgBIAEoCUIHukgEcgIQARJCCgZ0YWJsZXMYAiADKAsyKC5tZ210LnYxYWxwaGExLlBvc3RncmVzU291cmNlVGFibGVPcHRpb25CCLpIBZIBAggBIl8KGVBvc3RncmVzU291cmNlVGFibGVPcHRpb24SFgoFdGFibGUYASABKAlCB7pIBHICEAESGQoMd2hlcmVfY2xhdXNlGAIgASgJSACIAQFCDwoNX3doZXJlX2NsYXVzZSKyBAocTXlzcWxTb3VyY2VDb25uZWN0aW9uT3B0aW9ucxIjChtoYWx0X29uX25ld19jb2x1bW5fYWRkaXRpb24YASABKAgSNwoHc2NoZW1hcxgCIAMoCzImLm1nbXQudjFhbHBoYTEuTXlzcWxTb3VyY2VTY2hlbWFPcHRpb24SHwoNY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQESKQohc3Vic2V0X2J5X2ZvcmVpZ25fa2V5X2NvbnN0cmFpbnRzGAQgASgIEmIKF2NvbHVtbl9yZW1vdmFsX3N0cmF0ZWd5GAUgASgLMkEubWdtdC52MWFscGhhMS5NeXNxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneRqDAgoVQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5El0KCGhhbHRfam9iGAEgASgLMkkubWdtdC52MWFscGhhMS5NeXNxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneS5IYWx0Sm9iSAASZQoMY29udGludWVfam9iGAIgASgLMk0ubWdtdC52MWFscGhhMS5NeXNxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneS5Db250aW51ZUpvYkgAGgkKB0hhbHRKb2IaDQoLQ29udGludWVKb2JCCgoIc3RyYXRlZ3kicwoXTXlzcWxTb3VyY2VTY2hlbWFPcHRpb24SFwoGc2NoZW1hGAEgASgJQge6SARyAhABEj8KBnRhYmxlcxgCIAMoCzIlLm1nbXQudjFhbHBoYTEuTXlzcWxTb3VyY2VUYWJsZU9wdGlvbkIIukgFkgECCAEiXAoWTXlzcWxTb3VyY2VUYWJsZU9wdGlvbhIWCgV0YWJsZRgBIAEoCUIHukgEcgIQARIZCgx3aGVyZV9jbGF1c2UYAiABKAlIAIgBAUIPCg1fd2hlcmVfY2xhdXNlIrIEChxNc3NxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zEiMKG2hhbHRfb25fbmV3X2NvbHVtbl9hZGRpdGlvbhgBIAEoCBI3CgdzY2hlbWFzGAIgAygLMiYubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZVNjaGVtYU9wdGlvbhIfCg1jb25uZWN0aW9uX2lkGAMgASgJQgi6SAVyA7ABARIpCiFzdWJzZXRfYnlfZm9yZWlnbl9rZXlfY29uc3RyYWludHMYBCABKAgSYgoXY29sdW1uX3JlbW92YWxfc3RyYXRlZ3kYBSABKAsyQS5tZ210LnYxYWxwaGExLk1zc3FsU291cmNlQ29ubmVjdGlvbk9wdGlvbnMuQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5GoMCChVDb2x1bW5SZW1vdmFsU3RyYXRlZ3kSXQoIaGFsdF9qb2IYASABKAsySS5tZ210LnYxYWxwaGExLk1zc3FsU291cmNlQ29ubmVjdGlvbk9wdGlvbnMuQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5LkhhbHRKb2JIABJlCgxjb250aW51ZV9qb2IYAiABKAsyTS5tZ210LnYxYWxwaGExLk1zc3FsU291cmNlQ29ubmVjdGlvbk9wdGlvbnMuQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5LkNvbnRpbnVlSm9iSAAaCQoHSGFsdEpvYhoNCgtDb250aW51ZUpvYkIKCghzdHJhdGVneSJzChdNc3NxbFNvdXJjZVNjaGVtYU9wdGlvbhIXCgZzY2hlbWEYASABKAlCB7pIBHICEAESPwoGdGFibGVzGAIgAygLMiUubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZVRhYmxlT3B0aW9uQgi6SAWSAQIIASJcChZNc3NxbFNvdXJjZVRhYmxlT3B0aW9uEhYKBXRhYmxlGAEgASgJQge6SARyAhABEhkKDHdoZXJlX2NsYXVzZRgCIAEoCUgAiAEBQg8KDV93aGVyZV9jbGF1c2UiPwocQXdzUzNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucxIfCg1jb25uZWN0aW9uX2lkGAEgASgJQgi6SAVyA7ABASLbBAoVSm9iRGVzdGluYXRpb25PcHRpb25zEk8KEHBvc3RncmVzX29wdGlvbnMYASABKAsyMy5tZ210LnYxYWxwaGExLlBvc3RncmVzRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9uc0gAEkoKDmF3c19zM19vcHRpb25zGAIgASgLMjAubWdtdC52MWFscGhhMS5Bd3NTM0Rlc3RpbmF0aW9uQ29ubmVjdGlvbk9wdGlvbnNIABJJCg1teXNxbF9vcHRpb25zGAMgASgLMjAubWdtdC52MWFscGhhMS5NeXNxbERlc3RpbmF0aW9uQ29ubmVjdGlvbk9wdGlvbnNIABJNCg9tb25nb2RiX29wdGlvbnMYBCABKAsyMi5tZ210LnYxYWxwaGExLk1vbmdvREJEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSAASXgoYZ2NwX2Nsb3Vkc3RvcmFnZV9vcHRpb25zGAUgASgLMjoubWdtdC52MWFscGhhMS5HY3BDbG91ZFN0b3JhZ2VEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSAASTwoQZHluYW1vZGJfb3B0aW9ucxgGIAEoCzIzLm1nbXQudjFhbHBoYTEuRHluYW1vREJEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSAASSQoNbXNzcWxfb3B0aW9ucxgHIAEoCzIwLm1nbXQudjFhbHBoYTEuTXNzcWxEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSABCDwoGY29uZmlnEgW6SAIIASIlCiNNb25nb0RCRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucyItCitHY3BDbG91ZFN0b3JhZ2VEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zIm4KJER5bmFtb0RCRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucxJGCg50YWJsZV9tYXBwaW5ncxgBIAMoCzIuLm1nbXQudjFhbHBoYTEuRHluYW1vREJEZXN0aW5hdGlvblRhYmxlTWFwcGluZyJSCh9EeW5hbW9EQkRlc3RpbmF0aW9uVGFibGVNYXBwaW5nEhQKDHNvdXJjZV90YWJsZRgBIAEoCRIZChFkZXN0aW5hdGlvbl90YWJsZRgCIAEoCSLKAgokUG9zdGdyZXNEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zEkIKDnRydW5jYXRlX3RhYmxlGAEgASgLMioubWdtdC52MWFscGhhMS5Qb3N0Z3Jlc1RydW5jYXRlVGFibGVDb25maWcSGQoRaW5pdF90YWJsZV9zY2hlbWEYAiABKAgSPAoLb25fY29uZmxpY3QYAyABKAsyJy5tZ210LnYxYWxwaGExLlBvc3RncmVzT25Db25mbGljdENvbmZpZxIjChtza2lwX2ZvcmVpZ25fa2V5X3Zpb2xhdGlvbnMYBCABKAgSKQoFYmF0Y2gYBSABKAsyGi5tZ210LnYxYWxwaGExLkJhdGNoQ29uZmlnEiMKDW1heF9pbl9mbGlnaHQYBiABKA1CB7pIBCoCKAFIAIgBAUIQCg5fbWF4X2luX2ZsaWdodCKoAgoYUG9zdGdyZXNPbkNvbmZsaWN0Q29uZmlnEhIKCmRvX25vdGhpbmcYASABKAgSVgoHbm90aGluZxgCIAEoCzJDLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNPbkNvbmZsaWN0Q29uZmlnLlBvc3RncmVzT25Db25mbGljdERvTm90aGluZ0gAElIKBnVwZGF0ZRgDIAEoCzJALm1nbXQudjFhbHBoYTEuUG9zdGdyZXNPbkNvbmZsaWN0Q29uZmlnLlBvc3RncmVzT25Db25mbGljdFVwZGF0ZUgAGh0KG1Bvc3RncmVzT25Db25mbGljdERvTm90aGluZxoaChhQb3N0Z3Jlc09uQ29uZmxpY3RVcGRhdGVCEQoIc3RyYXRlZ3kSBbpIAggAIk4KG1Bvc3RncmVzVHJ1bmNhdGVUYWJsZUNvbmZpZxIeChZ0cnVuY2F0ZV9iZWZvcmVfaW5zZXJ0GAEgASgIEg8KB2Nhc2NhZGUYAiABKAgiwQIKIU15c3FsRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucxI/Cg50cnVuY2F0ZV90YWJsZRgBIAEoCzInLm1nbXQudjFhbHBoYTEuTXlzcWxUcnVuY2F0ZVRhYmxlQ29uZmlnEhkKEWluaXRfdGFibGVfc2NoZW1hGAIgASgIEjkKC29uX2NvbmZsaWN0GAMgASgLMiQubWdtdC52MWFscGhhMS5NeXNxbE9uQ29uZmxpY3RDb25maWcSIwobc2tpcF9mb3JlaWduX2tleV92aW9sYXRpb25zGAQgASgIEikKBWJhdGNoGAUgASgLMhoubWdtdC52MWFscGhhMS5CYXRjaENvbmZpZxIjCg1tYXhfaW5fZmxpZ2h0GAYgASgNQge6SAQqAigBSACIAQFCEAoOX21heF9pbl9mbGlnaHQiOgoYTXlzcWxUcnVuY2F0ZVRhYmxlQ29uZmlnEh4KFnRydW5jYXRlX2JlZm9yZV9pbnNlcnQYASABKAgikwIKFU15c3FsT25Db25mbGljdENvbmZpZxISCgpkb19ub3RoaW5nGAEgASgIElAKB25vdGhpbmcYAiABKAsyPS5tZ210LnYxYWxwaGExLk15c3FsT25Db25mbGljdENvbmZpZy5NeXNxbE9uQ29uZmxpY3REb05vdGhpbmdIABJMCgZ1cGRhdGUYAyABKAsyOi5tZ210LnYxYWxwaGExLk15c3FsT25Db25mbGljdENvbmZpZy5NeXNxbE9uQ29uZmxpY3RVcGRhdGVIABoaChhNeXNxbE9uQ29uZmxpY3REb05vdGhpbmcaFwoVTXlzcWxPbkNvbmZsaWN0VXBkYXRlQhEKCHN0cmF0ZWd5EgW6SAIIACLBAgohTXNzcWxEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zEj8KDnRydW5jYXRlX3RhYmxlGAEgASgLMicubWdtdC52MWFscGhhMS5Nc3NxbFRydW5jYXRlVGFibGVDb25maWcSGQoRaW5pdF90YWJsZV9zY2hlbWEYAiABKAgSOQoLb25fY29uZmxpY3QYAyABKAsyJC5tZ210LnYxYWxwaGExLk1zc3FsT25Db25mbGljdENvbmZpZxIjChtza2lwX2ZvcmVpZ25fa2V5X3Zpb2xhdGlvbnMYBCABKAgSKQoFYmF0Y2gYBSABKAsyGi5tZ210LnYxYWxwaGExLkJhdGNoQ29uZmlnEiMKDW1heF9pbl9mbGlnaHQYBiABKA1CB7pIBCoCKAFIAIgBAUIQCg5fbWF4X2luX2ZsaWdodCI6ChhNc3NxbFRydW5jYXRlVGFibGVDb25maWcSHgoWdHJ1bmNhdGVfYmVmb3JlX2luc2VydBgBIAEoCCIrChVNc3NxbE9uQ29uZmxpY3RDb25maWcSEgoKZG9fbm90aGluZxgBIAEoCCKOBAohQXdzUzNEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zElQKDXN0b3JhZ2VfY2xhc3MYASABKA4yPS5tZ210LnYxYWxwaGExLkF3c1MzRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucy5TdG9yYWdlQ2xhc3MSIwoNbWF4X2luX2ZsaWdodBgCIAEoDUIHukgEKgIoAUgAiAEBEhQKB3RpbWVvdXQYAyABKAlIAYgBARIpCgViYXRjaBgEIAEoCzIaLm1nbXQudjFhbHBoYTEuQmF0Y2hDb25maWcijgIKDFN0b3JhZ2VDbGFzcxIdChlTVE9SQUdFX0NMQVNTX1VOU1BFQ0lGSUVEEAASGgoWU1RPUkFHRV9DTEFTU19TVEFOREFSRBABEiQKIFNUT1JBR0VfQ0xBU1NfUkVEVUNFRF9SRURVTkRBTkNZEAISGQoVU1RPUkFHRV9DTEFTU19HTEFDSUVSEAMSHQoZU1RPUkFHRV9DTEFTU19TVEFOREFSRF9JQRAEEhwKGFNUT1JBR0VfQ0xBU1NfT05FWk9ORV9JQRAFEiUKIVNUT1JBR0VfQ0xBU1NfSU5URUxMSUdFTlRfVElFUklORxAGEh4KGlNUT1JBR0VfQ0xBU1NfREVFUF9BUkNISVZFEAdCEAoOX21heF9pbl9mbGlnaHRCCgoIX3RpbWVvdXQiSwoLQmF0Y2hDb25maWcSEgoFY291bnQYASABKA1IAIgBARITCgZwZXJpb2QYAiABKAlIAYgBAUIICgZfY291bnRCCQoHX3BlcmlvZCLuAwoQQ3JlYXRlSm9iUmVxdWVzdBIcCgphY2NvdW50X2lkGAEgASgJQgi6SAVyA7ABARIrCghqb2JfbmFtZRgCIAEoCUIZukgWchQyEl5bYS16MC05LV17MywxMDB9JBIaCg1jcm9uX3NjaGVkdWxlGAMgASgJSACIAQESKwoIbWFwcGluZ3MYBCADKAsyGS5tZ210LnYxYWxwaGExLkpvYk1hcHBpbmcSKAoGc291cmNlGAUgASgLMhgubWdtdC52MWFscGhhMS5Kb2JTb3VyY2USOQoMZGVzdGluYXRpb25zGAYgAygLMiMubWdtdC52MWFscGhhMS5DcmVhdGVKb2JEZXN0aW5hdGlvbhIYChBpbml0aWF0ZV9qb2JfcnVuGAcgASgIEjgKEHdvcmtmbG93X29wdGlvbnMYCCABKAsyHi5tZ210LnYxYWxwaGExLldvcmtmbG93T3B0aW9ucxI0CgxzeW5jX29wdGlvbnMYCSABKAsyHi5tZ210LnYxYWxwaGExLkFjdGl2aXR5T3B0aW9ucxJFChR2aXJ0dWFsX2ZvcmVpZ25fa2V5cxgKIAMoCzInLm1nbXQudjFhbHBoYTEuVmlydHVhbEZvcmVpZ25Db25zdHJhaW50QhAKDl9jcm9uX3NjaGVkdWxlImUKD1dvcmtmbG93T3B0aW9ucxIYCgtydW5fdGltZW91dBgIIAEoA0gAiAEBQg4KDF9ydW5fdGltZW91dEoECAEQAkoECAIQA0oECAMQBEoECAQQBUoECAUQBkoECAYQB0oECAcQCCLbAQoPQWN0aXZpdHlPcHRpb25zEi8KGXNjaGVkdWxlX3RvX2Nsb3NlX3RpbWVvdXQYASABKANCB7pIBCICKAFIAIgBARIsChZzdGFydF90b19jbG9zZV90aW1lb3V0GAIgASgDQge6SAQiAigBSAGIAQESMAoMcmV0cnlfcG9saWN5GAMgASgLMhoubWdtdC52MWFscGhhMS5SZXRyeVBvbGljeUIcChpfc2NoZWR1bGVfdG9fY2xvc2VfdGltZW91dEIZChdfc3RhcnRfdG9fY2xvc2VfdGltZW91dCJKCgtSZXRyeVBvbGljeRImChBtYXhpbXVtX2F0dGVtcHRzGAEgASgFQge6SAQaAigASACIAQFCEwoRX21heGltdW1fYXR0ZW1wdHMiNAoRQ3JlYXRlSm9iUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IiTwoVSm9iTWFwcGluZ1RyYW5zZm9ybWVyEjAKBmNvbmZpZxgDIAEoCzIgLm1nbXQudjFhbHBoYTEuVHJhbnNmb3JtZXJDb25maWdKBAgBEAIikQEKCkpvYk1hcHBpbmcSFwoGc2NoZW1hGAEgASgJQge6SARyAhABEhYKBXRhYmxlGAIgASgJQge6SARyAhABEhcKBmNvbHVtbhgDIAEoCUIHukgEcgIQARI5Cgt0cmFuc2Zvcm1lchgFIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iTWFwcGluZ1RyYW5zZm9ybWVyIiUKDUdldEpvYlJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIjEKDkdldEpvYlJlc3BvbnNlEh8KA2pvYhgBIAEoCzISLm1nbXQudjFhbHBoYTEuSm9iIl4KGFVwZGF0ZUpvYlNjaGVkdWxlUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESGgoNY3Jvbl9zY2hlZHVsZRgCIAEoCUgAiAEBQhAKDl9jcm9uX3NjaGVkdWxlIjwKGVVwZGF0ZUpvYlNjaGVkdWxlUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IiUgoPUGF1c2VKb2JSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABARINCgVwYXVzZRgCIAEoCBIRCgRub3RlGAMgASgJSACIAQFCBwoFX25vdGUiMwoQUGF1c2VKb2JSZXNwb25zZRIfCgNqb2IYASABKAsyEi5tZ210LnYxYWxwaGExLkpvYiLWAQogVXBkYXRlSm9iU291cmNlQ29ubmVjdGlvblJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEigKBnNvdXJjZRgCIAEoCzIYLm1nbXQudjFhbHBoYTEuSm9iU291cmNlEisKCG1hcHBpbmdzGAMgAygLMhkubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nEkUKFHZpcnR1YWxfZm9yZWlnbl9rZXlzGAQgAygLMicubWdtdC52MWFscGhhMS5WaXJ0dWFsRm9yZWlnbkNvbnN0cmFpbnQiRAohVXBkYXRlSm9iU291cmNlQ29ubmVjdGlvblJlc3BvbnNlEh8KA2pvYhgBIAEoCzISLm1nbXQudjFhbHBoYTEuSm9iImEKGlBvc3RncmVzU291cmNlU2NoZW1hU3Vic2V0EkMKEHBvc3RncmVzX3NjaGVtYXMYASADKAsyKS5tZ210LnYxYWxwaGExLlBvc3RncmVzU291cmNlU2NoZW1hT3B0aW9uIlgKF015c3FsU291cmNlU2NoZW1hU3Vic2V0Ej0KDW15c3FsX3NjaGVtYXMYASADKAsyJi5tZ210LnYxYWxwaGExLk15c3FsU291cmNlU2NoZW1hT3B0aW9uIlYKGkR5bmFtb0RCU291cmNlU2NoZW1hU3Vic2V0EjgKBnRhYmxlcxgBIAMoCzIoLm1nbXQudjFhbHBoYTEuRHluYW1vREJTb3VyY2VUYWJsZU9wdGlvbiJYChdNc3NxbFNvdXJjZVNjaGVtYVN1YnNldBI9Cg1tc3NxbF9zY2hlbWFzGAEgAygLMiYubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZVNjaGVtYU9wdGlvbiK+AgoYSm9iU291cmNlU3FsU3ViZXRTY2hlbWFzEkQKD3Bvc3RncmVzX3N1YnNldBgCIAEoCzIpLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VTY2hlbWFTdWJzZXRIABI+CgxteXNxbF9zdWJzZXQYAyABKAsyJi5tZ210LnYxYWxwaGExLk15c3FsU291cmNlU2NoZW1hU3Vic2V0SAASRAoPZHluYW1vZGJfc3Vic2V0GAQgASgLMikubWdtdC52MWFscGhhMS5EeW5hbW9EQlNvdXJjZVNjaGVtYVN1YnNldEgAEj4KDG1zc3FsX3N1YnNldBgFIAEoCzImLm1nbXQudjFhbHBoYTEuTXNzcWxTb3VyY2VTY2hlbWFTdWJzZXRIAEIQCgdzY2hlbWFzEgW6SAIIAUoECAEQAiKkAQonU2V0Sm9iU291cmNlU3FsQ29ubmVjdGlvblN1YnNldHNSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABARI4CgdzY2hlbWFzGAIgASgLMicubWdtdC52MWFscGhhMS5Kb2JTb3VyY2VTcWxTdWJldFNjaGVtYXMSKQohc3Vic2V0X2J5X2ZvcmVpZ25fa2V5X2NvbnN0cmFpbnRzGAMgASgIIksKKFNldEpvYlNvdXJjZVNxbENvbm5lY3Rpb25TdWJzZXRzUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IisQEKJVVwZGF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvblJlcXVlc3QSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARIfCg1jb25uZWN0aW9uX2lkGAIgASgJQgi6SAVyA7ABARI1CgdvcHRpb25zGAMgASgLMiQubWdtdC52MWFscGhhMS5Kb2JEZXN0aW5hdGlvbk9wdGlvbnMSFgoOZGVzdGluYXRpb25faWQYBCABKAkiSQomVXBkYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IiSQolRGVsZXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVxdWVzdBIgCg5kZXN0aW5hdGlvbl9pZBgBIAEoCUIIukgFcgOwAQEiKAomRGVsZXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVzcG9uc2UifQomQ3JlYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uc1JlcXVlc3QSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARI5CgxkZXN0aW5hdGlvbnMYAiADKAsyIy5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYkRlc3RpbmF0aW9uIkoKJ0NyZWF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvbnNSZXNwb25zZRIfCgNqb2IYASABKAsyEi5tZ210LnYxYWxwaGExLkpvYiIoChBEZWxldGVKb2JSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASITChFEZWxldGVKb2JSZXNwb25zZSJiChlJc0pvYk5hbWVBdmFpbGFibGVSZXF1ZXN0EicKBG5hbWUYASABKAlCGbpIFnIUMhJeW2EtejAtOS1dezMsMTAwfSQSHAoKYWNjb3VudF9pZBgCIAEoCUIIukgFcgOwAQEiMgoaSXNKb2JOYW1lQXZhaWxhYmxlUmVzcG9uc2USFAoMaXNfYXZhaWxhYmxlGAEgASgIIlUKEUdldEpvYlJ1bnNSZXF1ZXN0EhoKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQFIABIeCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABAUgAQgQKAmlkIj0KEkdldEpvYlJ1bnNSZXNwb25zZRInCghqb2JfcnVucxgBIAMoCzIVLm1nbXQudjFhbHBoYTEuSm9iUnVuIkQKEEdldEpvYlJ1blJlcXVlc3QSEgoKam9iX3J1bl9pZBgBIAEoCRIcCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABASI7ChFHZXRKb2JSdW5SZXNwb25zZRImCgdqb2JfcnVuGAEgASgLMhUubWdtdC52MWFscGhhMS5Kb2JSdW4iLwoTQ3JlYXRlSm9iUnVuUmVxdWVzdBIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBIhYKFENyZWF0ZUpvYlJ1blJlc3BvbnNlIkcKE0NhbmNlbEpvYlJ1blJlcXVlc3QSEgoKam9iX3J1bl9pZBgBIAEoCRIcCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABASIWChRDYW5jZWxKb2JSdW5SZXNwb25zZSK8BAoDSm9iEgoKAmlkGAEgASgJEhoKEmNyZWF0ZWRfYnlfdXNlcl9pZBgCIAEoCRIuCgpjcmVhdGVkX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIaChJ1cGRhdGVkX2J5X3VzZXJfaWQYBCABKAkSLgoKdXBkYXRlZF9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDAoEbmFtZRgGIAEoCRIoCgZzb3VyY2UYByABKAsyGC5tZ210LnYxYWxwaGExLkpvYlNvdXJjZRIzCgxkZXN0aW5hdGlvbnMYCCADKAsyHS5tZ210LnYxYWxwaGExLkpvYkRlc3RpbmF0aW9uEisKCG1hcHBpbmdzGAkgAygLMhkubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nEhoKDWNyb25fc2NoZWR1bGUYCiABKAlIAIgBARISCgphY2NvdW50X2lkGAsgASgJEjQKDHN5bmNfb3B0aW9ucxgMIAEoCzIeLm1nbXQudjFhbHBoYTEuQWN0aXZpdHlPcHRpb25zEjgKEHdvcmtmbG93X29wdGlvbnMYDSABKAsyHi5tZ210LnYxYWxwaGExLldvcmtmbG93T3B0aW9ucxJFChR2aXJ0dWFsX2ZvcmVpZ25fa2V5cxgOIAMoCzInLm1nbXQudjFhbHBoYTEuVmlydHVhbEZvcmVpZ25Db25zdHJhaW50QhAKDl9jcm9uX3NjaGVkdWxlIlIKDEpvYlJlY2VudFJ1bhIuCgpzdGFydF90aW1lGAEgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBISCgpqb2JfcnVuX2lkGAIgASgJIjMKF0dldEpvYlJlY2VudFJ1bnNSZXF1ZXN0EhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQEiTAoYR2V0Sm9iUmVjZW50UnVuc1Jlc3BvbnNlEjAKC3JlY2VudF9ydW5zGAEgAygLMhsubWdtdC52MWFscGhhMS5Kb2JSZWNlbnRSdW4iQQoLSm9iTmV4dFJ1bnMSMgoObmV4dF9ydW5fdGltZXMYASADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIjEKFUdldEpvYk5leHRSdW5zUmVxdWVzdBIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBIkcKFkdldEpvYk5leHRSdW5zUmVzcG9uc2USLQoJbmV4dF9ydW5zGAEgASgLMhoubWdtdC52MWFscGhhMS5Kb2JOZXh0UnVucyIvChNHZXRKb2JTdGF0dXNSZXF1ZXN0EhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQEiQAoUR2V0Sm9iU3RhdHVzUmVzcG9uc2USKAoGc3RhdHVzGAEgASgOMhgubWdtdC52MWFscGhhMS5Kb2JTdGF0dXMiVQoPSm9iU3RhdHVzUmVjb3JkEhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQESKAoGc3RhdHVzGAIgASgOMhgubWdtdC52MWFscGhhMS5Kb2JTdGF0dXMiNQoVR2V0Sm9iU3RhdHVzZXNSZXF1ZXN0EhwKCmFjY291bnRfaWQYASABKAlCCLpIBXIDsAEBIkoKFkdldEpvYlN0YXR1c2VzUmVzcG9uc2USMAoIc3RhdHVzZXMYASADKAsyHi5tZ210LnYxYWxwaGExLkpvYlN0YXR1c1JlY29yZCIiCg9BY3Rpdml0eUZhaWx1cmUSDwoHbWVzc2FnZRgBIAEoCSKjAQoPUGVuZGluZ0FjdGl2aXR5Ei0KBnN0YXR1cxgBIAEoDjIdLm1nbXQudjFhbHBoYTEuQWN0aXZpdHlTdGF0dXMSFQoNYWN0aXZpdHlfbmFtZRgCIAEoCRI5CgxsYXN0X2ZhaWx1cmUYAyABKAsyHi5tZ210LnYxYWxwaGExLkFjdGl2aXR5RmFpbHVyZUgAiAEBQg8KDV9sYXN0X2ZhaWx1cmUimQIKBkpvYlJ1bhIKCgJpZBgBIAEoCRIOCgZqb2JfaWQYAiABKAkSDAoEbmFtZRgDIAEoCRIrCgZzdGF0dXMYBCABKA4yGy5tZ210LnYxYWxwaGExLkpvYlJ1blN0YXR1cxIuCgpzdGFydGVkX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI1Cgxjb21wbGV0ZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSACIAQESOgoScGVuZGluZ19hY3Rpdml0aWVzGAggAygLMh4ubWdtdC52MWFscGhhMS5QZW5kaW5nQWN0aXZpdHlCDwoNX2NvbXBsZXRlZF9hdEoECAUQBiI8ChRKb2JSdW5FdmVudFRhc2tFcnJvchIPCgdtZXNzYWdlGAEgASgJEhMKC3JldHJ5X3N0YXRlGAIgASgJIo8BCg9Kb2JSdW5FdmVudFRhc2sSCgoCaWQYASABKAMSDAoEdHlwZRgCIAEoCRIuCgpldmVudF90aW1lGAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgVlcnJvchgEIAEoCzIjLm1nbXQudjFhbHBoYTEuSm9iUnVuRXZlbnRUYXNrRXJyb3IiMwoSSm9iUnVuU3luY01ldGFkYXRhEg4KBnNjaGVtYRgBIAEoCRINCgV0YWJsZRgCIAEoCSJkChNKb2JSdW5FdmVudE1ldGFkYXRhEjoKDXN5bmNfbWV0YWRhdGEYASABKAsyIS5tZ210LnYxYWxwaGExLkpvYlJ1blN5bmNNZXRhZGF0YUgAQhEKCG1ldGFkYXRhEgW6SAIIASLsAQoLSm9iUnVuRXZlbnQSCgoCaWQYASABKAMSDAoEdHlwZRgCIAEoCRIuCgpzdGFydF90aW1lGAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjbG9zZV90aW1lGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI0CghtZXRhZGF0YRgFIAEoCzIiLm1nbXQudjFhbHBoYTEuSm9iUnVuRXZlbnRNZXRhZGF0YRItCgV0YXNrcxgGIAMoCzIeLm1nbXQudjFhbHBoYTEuSm9iUnVuRXZlbnRUYXNrIkoKFkdldEpvYlJ1bkV2ZW50c1JlcXVlc3QSEgoKam9iX3J1bl9pZBgBIAEoCRIcCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABASJeChdHZXRKb2JSdW5FdmVudHNSZXNwb25zZRIqCgZldmVudHMYASADKAsyGi5tZ210LnYxYWxwaGExLkpvYlJ1bkV2ZW50EhcKD2lzX3J1bl9jb21wbGV0ZRgCIAEoCCJHChNEZWxldGVKb2JSdW5SZXF1ZXN0EhIKCmpvYl9ydW5faWQYASABKAkSHAoKYWNjb3VudF9pZBgCIAEoCUIIukgFcgOwAQEiFgoURGVsZXRlSm9iUnVuUmVzcG9uc2UiSgoWVGVybWluYXRlSm9iUnVuUmVxdWVzdBISCgpqb2JfcnVuX2lkGAEgASgJEhwKCmFjY291bnRfaWQYAiABKAlCCLpIBXIDsAEBIhkKF1Rlcm1pbmF0ZUpvYlJ1blJlc3BvbnNlIvEBChpHZXRKb2JSdW5Mb2dzU3RyZWFtUmVxdWVzdBISCgpqb2JfcnVuX2lkGAEgASgJEhwKCmFjY291bnRfaWQYAiABKAlCCLpIBXIDsAEBEigKBndpbmRvdxgDIAEoDjIYLm1nbXQudjFhbHBoYTEuTG9nV2luZG93EhMKC3Nob3VsZF90YWlsGAQgASgIEiMKDW1heF9sb2dfbGluZXMYBSABKANCB7pIBCICKAFIAIgBARIrCgpsb2dfbGV2ZWxzGAYgAygOMhcubWdtdC52MWFscGhhMS5Mb2dMZXZlbEIQCg5fbWF4X2xvZ19saW5lcyJxChtHZXRKb2JSdW5Mb2dzU3RyZWFtUmVzcG9uc2USEAoIbG9nX2xpbmUYASABKAkSMgoJdGltZXN0YW1wGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEgAiAEBQgwKCl90aW1lc3RhbXAibgocU2V0Sm9iV29ya2Zsb3dPcHRpb25zUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESOAoQd29yZmtsb3dfb3B0aW9ucxgCIAEoCzIeLm1nbXQudjFhbHBoYTEuV29ya2Zsb3dPcHRpb25zIkAKHVNldEpvYldvcmtmbG93T3B0aW9uc1Jlc3BvbnNlEh8KA2pvYhgBIAEoCzISLm1nbXQudjFhbHBoYTEuSm9iImYKGFNldEpvYlN5bmNPcHRpb25zUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESNAoMc3luY19vcHRpb25zGAIgASgLMh4ubWdtdC52MWFscGhhMS5BY3Rpdml0eU9wdGlvbnMiPAoZU2V0Sm9iU3luY09wdGlvbnNSZXNwb25zZRIfCgNqb2IYASABKAsyEi5tZ210LnYxYWxwaGExLkpvYiKRAgoaVmFsaWRhdGVKb2JNYXBwaW5nc1JlcXVlc3QSHAoKYWNjb3VudF9pZBgBIAEoCUIIukgFcgOwAQESKwoIbWFwcGluZ3MYAiADKAsyGS5tZ210LnYxYWxwaGExLkpvYk1hcHBpbmcSHwoNY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQESRQoUdmlydHVhbF9mb3JlaWduX2tleXMYBCADKAsyJy5tZ210LnYxYWxwaGExLlZpcnR1YWxGb3JlaWduQ29uc3RyYWludBIxCgpqb2Jfc291cmNlGAUgASgLMhgubWdtdC52MWFscGhhMS5Kb2JTb3VyY2VIAIgBAUINCgtfam9iX3NvdXJjZSJMCgtDb2x1bW5FcnJvchIOCgZzY2hlbWEYASABKAkSDQoFdGFibGUYAiABKAkSDgoGY29sdW1uGAMgASgJEg4KBmVycm9ycxgEIAMoCSJQCg1Db2x1bW5XYXJuaW5nEg4KBnNjaGVtYRgBIAEoCRINCgV0YWJsZRgCIAEoCRIOCgZjb2x1bW4YAyABKAkSEAoId2FybmluZ3MYBSADKAkiHwoNRGF0YWJhc2VFcnJvchIOCgZlcnJvcnMYASADKAkivgEKG1ZhbGlkYXRlSm9iTWFwcGluZ3NSZXNwb25zZRIxCg1jb2x1bW5fZXJyb3JzGAEgAygLMhoubWdtdC52MWFscGhhMS5Db2x1bW5FcnJvchI1Cg9kYXRhYmFzZV9lcnJvcnMYAiABKAsyHC5tZ210LnYxYWxwaGExLkRhdGFiYXNlRXJyb3ISNQoPY29sdW1uX3dhcm5pbmdzGAMgAygLMhwubWdtdC52MWFscGhhMS5Db2x1bW5XYXJuaW5nIkMKEVZpcnR1YWxGb3JlaWduS2V5Eg4KBnNjaGVtYRgBIAEoCRINCgV0YWJsZRgCIAEoCRIPCgdjb2x1bW5zGAMgAygJIoEBChhWaXJ0dWFsRm9yZWlnbkNvbnN0cmFpbnQSDgoGc2NoZW1hGAEgASgJEg0KBXRhYmxlGAIgASgJEg8KB2NvbHVtbnMYAyADKAkSNQoLZm9yZWlnbl9rZXkYBCABKAsyIC5tZ210LnYxYWxwaGExLlZpcnR1YWxGb3JlaWduS2V5ImcKDVJ1bkNvbnRleHRLZXkSGwoKam9iX3J1bl9pZBgBIAEoCUIHukgEcgIQARIcCgtleHRlcm5hbF9pZBgCIAEoCUIHukgEcgIQARIbCgphY2NvdW50X2lkGAMgASgJQge6SARyAhABIkAKFEdldFJ1bkNvbnRleHRSZXF1ZXN0EigKAmlkGAEgASgLMhwubWdtdC52MWFscGhhMS5SdW5Db250ZXh0S2V5IiYKFUdldFJ1bkNvbnRleHRSZXNwb25zZRINCgV2YWx1ZRgBIAEoDCJPChRTZXRSdW5Db250ZXh0UmVxdWVzdBIoCgJpZBgBIAEoCzIcLm1nbXQudjFhbHBoYTEuUnVuQ29udGV4dEtleRINCgV2YWx1ZRgCIAEoDCIXChVTZXRSdW5Db250ZXh0UmVzcG9uc2UiUAoVU2V0UnVuQ29udGV4dHNSZXF1ZXN0EigKAmlkGAEgASgLMhwubWdtdC52MWFscGhhMS5SdW5Db250ZXh0S2V5Eg0KBXZhbHVlGAIgASgMIhgKFlNldFJ1bkNvbnRleHRzUmVzcG9uc2UivAIKB0pvYkhvb2sSCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCRIOCgZqb2JfaWQYBCABKAkSLAoGY29uZmlnGAUgASgLMhwubWdtdC52MWFscGhhMS5Kb2JIb29rQ29uZmlnEhoKEmNyZWF0ZWRfYnlfdXNlcl9pZBgGIAEoCRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIaChJ1cGRhdGVkX2J5X3VzZXJfaWQYCCABKAkSLgoKdXBkYXRlZF9hdBgJIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDwoHZW5hYmxlZBgKIAEoCBIbCghwcmlvcml0eRgLIAEoDUIJukgGKgQYZCgAIq8BCgpOZXdKb2JIb29rEicKBG5hbWUYASABKAlCGbpIFnIUMhJeW2EtejAtOS1dezMsMTAwfSQSHAoLZGVzY3JpcHRpb24YAiABKAlCB7pIBHICEAESLAoGY29uZmlnGAMgASgLMhwubWdtdC52MWFscGhhMS5Kb2JIb29rQ29uZmlnEg8KB2VuYWJsZWQYBCABKAgSGwoIcHJpb3JpdHkYBSABKA1CCbpIBioEGGQoACKIAwoNSm9iSG9va0NvbmZpZxI2CgNzcWwYBSABKAsyJy5tZ210LnYxYWxwaGExLkpvYkhvb2tDb25maWcuSm9iU3FsSG9va0gAGpUCCgpKb2JTcWxIb29rEhYKBXF1ZXJ5GAEgASgJQge6SARyAhABEh8KDWNvbm5lY3Rpb25faWQYAiABKAlCCLpIBXIDsAEBEj4KBnRpbWluZxgDIAEoCzIuLm1nbXQudjFhbHBoYTEuSm9iSG9va0NvbmZpZy5Kb2JTcWxIb29rLlRpbWluZxqNAQoGVGltaW5nEjcKCHByZV9zeW5jGAMgASgLMiMubWdtdC52MWFscGhhMS5Kb2JIb29rVGltaW5nUHJlU3luY0gAEjkKCXBvc3Rfc3luYxgEIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iSG9va1RpbWluZ1Bvc3RTeW5jSABCDwoGdGltaW5nEgW6SAIIAUIPCgZjb25maWcSBbpIAggBSgQIARACSgQIAhADSgQIAxAESgQIBBAFIhYKFEpvYkhvb2tUaW1pbmdQcmVTeW5jIhcKFUpvYkhvb2tUaW1pbmdQb3N0U3luYyIuChJHZXRKb2JIb29rc1JlcXVlc3QSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABASI8ChNHZXRKb2JIb29rc1Jlc3BvbnNlEiUKBWhvb2tzGAEgAygLMhYubWdtdC52MWFscGhhMS5Kb2JIb29rIikKEUdldEpvYkhvb2tSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASI6ChJHZXRKb2JIb29rUmVzcG9uc2USJAoEaG9vaxgBIAEoCzIWLm1nbXQudjFhbHBoYTEuSm9iSG9vayJPChRDcmVhdGVKb2JIb29rUmVxdWVzdBIOCgZqb2JfaWQYASABKAkSJwoEaG9vaxgCIAEoCzIZLm1nbXQudjFhbHBoYTEuTmV3Sm9iSG9vayI9ChVDcmVhdGVKb2JIb29rUmVzcG9uc2USJAoEaG9vaxgBIAEoCzIWLm1nbXQudjFhbHBoYTEuSm9iSG9vayIsChREZWxldGVKb2JIb29rUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQEiFwoVRGVsZXRlSm9iSG9va1Jlc3BvbnNlIj0KHUlzSm9iSG9va05hbWVBdmFpbGFibGVSZXF1ZXN0Eg4KBmpvYl9pZBgBIAEoCRIMCgRuYW1lGAIgASgJIjYKHklzSm9iSG9va05hbWVBdmFpbGFibGVSZXNwb25zZRIUCgxpc19hdmFpbGFibGUYASABKAgizwEKFFVwZGF0ZUpvYkhvb2tSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABARInCgRuYW1lGAIgASgJQhm6SBZyFDISXlthLXowLTktXXszLDEwMH0kEhwKC2Rlc2NyaXB0aW9uGAMgASgJQge6SARyAhABEiwKBmNvbmZpZxgEIAEoCzIcLm1nbXQudjFhbHBoYTEuSm9iSG9va0NvbmZpZxIPCgdlbmFibGVkGAUgASgIEhsKCHByaW9yaXR5GAYgASgNQgm6SAYqBBhkKAAiPQoVVXBkYXRlSm9iSG9va1Jlc3BvbnNlEiQKBGhvb2sYASABKAsyFi5tZ210LnYxYWxwaGExLkpvYkhvb2siQQoYU2V0Sm9iSG9va0VuYWJsZWRSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABARIPCgdlbmFibGVkGAIgASgIIkEKGVNldEpvYkhvb2tFbmFibGVkUmVzcG9uc2USJAoEaG9vaxgBIAEoCzIWLm1nbXQudjFhbHBoYTEuSm9iSG9vayLPAQogR2V0QWN0aXZlSm9iSG9va3NCeVRpbWluZ1JlcXVlc3QSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARJGCgZ0aW1pbmcYAiABKA4yNi5tZ210LnYxYWxwaGExLkdldEFjdGl2ZUpvYkhvb2tzQnlUaW1pbmdSZXF1ZXN0LlRpbWluZyJJCgZUaW1pbmcSFgoSVElNSU5HX1VOU1BFQ0lGSUVEEAASEgoOVElNSU5HX1BSRVNZTkMQARITCg9USU1JTkdfUE9TVFNZTkMQAiJKCiFHZXRBY3RpdmVKb2JIb29rc0J5VGltaW5nUmVzcG9uc2USJQoFaG9va3MYASADKAsyFi5tZ210LnYxYWxwaGExLkpvYkhvb2sqbwoJSm9iU3RhdHVzEhoKFkpPQl9TVEFUVVNfVU5TUEVDSUZJRUQQABIWChJKT0JfU1RBVFVTX0VOQUJMRUQQARIVChFKT0JfU1RBVFVTX1BBVVNFRBADEhcKE0pPQl9TVEFUVVNfRElTQUJMRUQQBCqnAQoOQWN0aXZpdHlTdGF0dXMSHwobQUNUSVZJVFlfU1RBVFVTX1VOU1BFQ0lGSUVEEAASHQoZQUNUSVZJVFlfU1RBVFVTX1NDSEVEVUxFRBABEhsKF0FDVElWSVRZX1NUQVRVU19TVEFSVEVEEAISHAoYQUNUSVZJVFlfU1RBVFVTX0NBTkNFTEVEEAMSGgoWQUNUSVZJVFlfU1RBVFVTX0ZBSUxFRBAEKpICCgxKb2JSdW5TdGF0dXMSHgoaSk9CX1JVTl9TVEFUVVNfVU5TUEVDSUZJRUQQABIaChZKT0JfUlVOX1NUQVRVU19QRU5ESU5HEAESGgoWSk9CX1JVTl9TVEFUVVNfUlVOTklORxACEhsKF0pPQl9SVU5fU1RBVFVTX0NPTVBMRVRFEAMSGAoUSk9CX1JVTl9TVEFUVVNfRVJST1IQBBIbChdKT0JfUlVOX1NUQVRVU19DQU5DRUxFRBAFEh0KGUpPQl9SVU5fU1RBVFVTX1RFUk1JTkFURUQQBhIZChVKT0JfUlVOX1NUQVRVU19GQUlMRUQQBxIcChhKT0JfUlVOX1NUQVRVU19USU1FRF9PVVQQCCp8CglMb2dXaW5kb3cSIgoeTE9HX1dJTkRPV19OT19USU1FX1VOU1BFQ0lGSUVEEAASGgoWTE9HX1dJTkRPV19GSUZURUVOX01JThABEhcKE0xPR19XSU5ET1dfT05FX0hPVVIQAhIWChJMT0dfV0lORE9XX09ORV9EQVkQAyp3CghMb2dMZXZlbBIZChVMT0dfTEVWRUxfVU5TUEVDSUZJRUQQABITCg9MT0dfTEVWRUxfREVCVUcQARISCg5MT0dfTEVWRUxfSU5GTxACEhIKDkxPR19MRVZFTF9XQVJOEAMSEwoPTE9HX0xFVkVMX0VSUk9SEAQy+B4KCkpvYlNlcnZpY2USTQoHR2V0Sm9icxIdLm1nbXQudjFhbHBoYTEuR2V0Sm9ic1JlcXVlc3QaHi5tZ210LnYxYWxwaGExLkdldEpvYnNSZXNwb25zZSIDkAIBEkoKBkdldEpvYhIcLm1nbXQudjFhbHBoYTEuR2V0Sm9iUmVxdWVzdBodLm1nbXQudjFhbHBoYTEuR2V0Sm9iUmVzcG9uc2UiA5ACARJQCglDcmVhdGVKb2ISHy5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYlJlcXVlc3QaIC5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYlJlc3BvbnNlIgASUAoJRGVsZXRlSm9iEh8ubWdtdC52MWFscGhhMS5EZWxldGVKb2JSZXF1ZXN0GiAubWdtdC52MWFscGhhMS5EZWxldGVKb2JSZXNwb25zZSIAEm4KEklzSm9iTmFtZUF2YWlsYWJsZRIoLm1nbXQudjFhbHBoYTEuSXNKb2JOYW1lQXZhaWxhYmxlUmVxdWVzdBopLm1nbXQudjFhbHBoYTEuSXNKb2JOYW1lQXZhaWxhYmxlUmVzcG9uc2UiA5ACARJoChFVcGRhdGVKb2JTY2hlZHVsZRInLm1nbXQudjFhbHBoYTEuVXBkYXRlSm9iU2NoZWR1bGVSZXF1ZXN0GigubWdtdC52MWFscGhhMS5VcGRhdGVKb2JTY2hlZHVsZVJlc3BvbnNlIgASgAEKGVVwZGF0ZUpvYlNvdXJjZUNvbm5lY3Rpb24SLy5tZ210LnYxYWxwaGExLlVwZGF0ZUpvYlNvdXJjZUNvbm5lY3Rpb25SZXF1ZXN0GjAubWdtdC52MWFscGhhMS5VcGRhdGVKb2JTb3VyY2VDb25uZWN0aW9uUmVzcG9uc2UiABKVAQogU2V0Sm9iU291cmNlU3FsQ29ubmVjdGlvblN1YnNldHMSNi5tZ210LnYxYWxwaGExLlNldEpvYlNvdXJjZVNxbENvbm5lY3Rpb25TdWJzZXRzUmVxdWVzdBo3Lm1nbXQudjFhbHBoYTEuU2V0Sm9iU291cmNlU3FsQ29ubmVjdGlvblN1YnNldHNSZXNwb25zZSIAEo8BCh5VcGRhdGVKb2JEZXN0aW5hdGlvbkNvbm5lY3Rpb24SNC5tZ210LnYxYWxwaGExLlVwZGF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvblJlcXVlc3QaNS5tZ210LnYxYWxwaGExLlVwZGF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvblJlc3BvbnNlIgASjwEKHkRlbGV0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvbhI0Lm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVxdWVzdBo1Lm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVzcG9uc2UiABKSAQofQ3JlYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9ucxI1Lm1nbXQudjFhbHBoYTEuQ3JlYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uc1JlcXVlc3QaNi5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvbnNSZXNwb25zZSIAEk0KCFBhdXNlSm9iEh4ubWdtdC52MWFscGhhMS5QYXVzZUpvYlJlcXVlc3QaHy5tZ210LnYxYWxwaGExLlBhdXNlSm9iUmVzcG9uc2UiABJoChBHZXRKb2JSZWNlbnRSdW5zEiYubWdtdC52MWFscGhhMS5HZXRKb2JSZWNlbnRSdW5zUmVxdWVzdBonLm1nbXQudjFhbHBoYTEuR2V0Sm9iUmVjZW50UnVuc1Jlc3BvbnNlIgOQAgESYgoOR2V0Sm9iTmV4dFJ1bnMSJC5tZ210LnYxYWxwaGExLkdldEpvYk5leHRSdW5zUmVxdWVzdBolLm1nbXQudjFhbHBoYTEuR2V0Sm9iTmV4dFJ1bnNSZXNwb25zZSIDkAIBElwKDEdldEpvYlN0YXR1cxIiLm1nbXQudjFhbHBoYTEuR2V0Sm9iU3RhdHVzUmVxdWVzdBojLm1nbXQudjFhbHBoYTEuR2V0Sm9iU3RhdHVzUmVzcG9uc2UiA5ACARJiCg5HZXRKb2JTdGF0dXNlcxIkLm1nbXQudjFhbHBoYTEuR2V0Sm9iU3RhdHVzZXNSZXF1ZXN0GiUubWdtdC52MWFscGhhMS5HZXRKb2JTdGF0dXNlc1Jlc3BvbnNlIgOQAgESVgoKR2V0Sm9iUnVucxIgLm1nbXQudjFhbHBoYTEuR2V0Sm9iUnVuc1JlcXVlc3QaIS5tZ210LnYxYWxwaGExLkdldEpvYlJ1bnNSZXNwb25zZSIDkAIBEmUKD0dldEpvYlJ1bkV2ZW50cxIlLm1nbXQudjFhbHBoYTEuR2V0Sm9iUnVuRXZlbnRzUmVxdWVzdBomLm1nbXQudjFhbHBoYTEuR2V0Sm9iUnVuRXZlbnRzUmVzcG9uc2UiA5ACARJTCglHZXRKb2JSdW4SHy5tZ210LnYxYWxwaGExLkdldEpvYlJ1blJlcXVlc3QaIC5tZ210LnYxYWxwaGExLkdldEpvYlJ1blJlc3BvbnNlIgOQAgESWQoMRGVsZXRlSm9iUnVuEiIubWdtdC52MWFscGhhMS5EZWxldGVKb2JSdW5SZXF1ZXN0GiMubWdtdC52MWFscGhhMS5EZWxldGVKb2JSdW5SZXNwb25zZSIAElkKDENyZWF0ZUpvYlJ1bhIiLm1nbXQudjFhbHBoYTEuQ3JlYXRlSm9iUnVuUmVxdWVzdBojLm1nbXQudjFhbHBoYTEuQ3JlYXRlSm9iUnVuUmVzcG9uc2UiABJZCgxDYW5jZWxKb2JSdW4SIi5tZ210LnYxYWxwaGExLkNhbmNlbEpvYlJ1blJlcXVlc3QaIy5tZ210LnYxYWxwaGExLkNhbmNlbEpvYlJ1blJlc3BvbnNlIgASYgoPVGVybWluYXRlSm9iUnVuEiUubWdtdC52MWFscGhhMS5UZXJtaW5hdGVKb2JSdW5SZXF1ZXN0GiYubWdtdC52MWFscGhhMS5UZXJtaW5hdGVKb2JSdW5SZXNwb25zZSIAEnAKE0dldEpvYlJ1bkxvZ3NTdHJlYW0SKS5tZ210LnYxYWxwaGExLkdldEpvYlJ1bkxvZ3NTdHJlYW1SZXF1ZXN0GioubWdtdC52MWFscGhhMS5HZXRKb2JSdW5Mb2dzU3RyZWFtUmVzcG9uc2UiADABEnQKFVNldEpvYldvcmtmbG93T3B0aW9ucxIrLm1nbXQudjFhbHBoYTEuU2V0Sm9iV29ya2Zsb3dPcHRpb25zUmVxdWVzdBosLm1nbXQudjFhbHBoYTEuU2V0Sm9iV29ya2Zsb3dPcHRpb25zUmVzcG9uc2UiABJoChFTZXRKb2JTeW5jT3B0aW9ucxInLm1nbXQudjFhbHBoYTEuU2V0Sm9iU3luY09wdGlvbnNSZXF1ZXN0GigubWdtdC52MWFscGhhMS5TZXRKb2JTeW5jT3B0aW9uc1Jlc3BvbnNlIgASbgoTVmFsaWRhdGVKb2JNYXBwaW5ncxIpLm1nbXQudjFhbHBoYTEuVmFsaWRhdGVKb2JNYXBwaW5nc1JlcXVlc3QaKi5tZ210LnYxYWxwaGExLlZhbGlkYXRlSm9iTWFwcGluZ3NSZXNwb25zZSIAElwKDUdldFJ1bkNvbnRleHQSIy5tZ210LnYxYWxwaGExLkdldFJ1bkNvbnRleHRSZXF1ZXN0GiQubWdtdC52MWFscGhhMS5HZXRSdW5Db250ZXh0UmVzcG9uc2UiABJcCg1TZXRSdW5Db250ZXh0EiMubWdtdC52MWFscGhhMS5TZXRSdW5Db250ZXh0UmVxdWVzdBokLm1nbXQudjFhbHBoYTEuU2V0UnVuQ29udGV4dFJlc3BvbnNlIgASYQoOU2V0UnVuQ29udGV4dHMSJC5tZ210LnYxYWxwaGExLlNldFJ1bkNvbnRleHRzUmVxdWVzdBolLm1nbXQudjFhbHBoYTEuU2V0UnVuQ29udGV4dHNSZXNwb25zZSIAKAESWQoLR2V0Sm9iSG9va3MSIS5tZ210LnYxYWxwaGExLkdldEpvYkhvb2tzUmVxdWVzdBoiLm1nbXQudjFhbHBoYTEuR2V0Sm9iSG9va3NSZXNwb25zZSIDkAIBElYKCkdldEpvYkhvb2sSIC5tZ210LnYxYWxwaGExLkdldEpvYkhvb2tSZXF1ZXN0GiEubWdtdC52MWFscGhhMS5HZXRKb2JIb29rUmVzcG9uc2UiA5ACARJcCg1DcmVhdGVKb2JIb29rEiMubWdtdC52MWFscGhhMS5DcmVhdGVKb2JIb29rUmVxdWVzdBokLm1nbXQudjFhbHBoYTEuQ3JlYXRlSm9iSG9va1Jlc3BvbnNlIgASXAoNRGVsZXRlSm9iSG9vaxIjLm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iSG9va1JlcXVlc3QaJC5tZ210LnYxYWxwaGExLkRlbGV0ZUpvYkhvb2tSZXNwb25zZSIAEncKFklzSm9iSG9va05hbWVBdmFpbGFibGUSLC5tZ210LnYxYWxwaGExLklzSm9iSG9va05hbWVBdmFpbGFibGVSZXF1ZXN0Gi0ubWdtdC52MWFscGhhMS5Jc0pvYkhvb2tOYW1lQXZhaWxhYmxlUmVzcG9uc2UiABJcCg1VcGRhdGVKb2JIb29rEiMubWdtdC52MWFscGhhMS5VcGRhdGVKb2JIb29rUmVxdWVzdBokLm1nbXQudjFhbHBoYTEuVXBkYXRlSm9iSG9va1Jlc3BvbnNlIgASaAoRU2V0Sm9iSG9va0VuYWJsZWQSJy5tZ210LnYxYWxwaGExLlNldEpvYkhvb2tFbmFibGVkUmVxdWVzdBooLm1nbXQudjFhbHBoYTEuU2V0Sm9iSG9va0VuYWJsZWRSZXNwb25zZSIAEoMBChlHZXRBY3RpdmVKb2JIb29rc0J5VGltaW5nEi8ubWdtdC52MWFscGhhMS5HZXRBY3RpdmVKb2JIb29rc0J5VGltaW5nUmVxdWVzdBowLm1nbXQudjFhbHBoYTEuR2V0QWN0aXZlSm9iSG9va3NCeVRpbWluZ1Jlc3BvbnNlIgOQAgFCxAEKEWNvbS5tZ210LnYxYWxwaGExQghKb2JQcm90b1ABWlBnaXRodWIuY29tL251Y2xldXNjbG91ZC9uZW9zeW5jL2JhY2tlbmQvZ2VuL2dvL3Byb3Rvcy9tZ210L3YxYWxwaGExO21nbXR2MWFscGhhMaICA01YWKoCDU1nbXQuVjFhbHBoYTHKAg1NZ210XFYxYWxwaGEx4gIZTWdtdFxWMWFscGhhMVxHUEJNZXRhZGF0YeoCDk1nbXQ6OlYxYWxwaGExYgZwcm90bzM", [file_buf_validate_validate, file_google_protobuf_timestamp, file_mgmt_v1alpha1_transformer]);
+ fileDesc("ChdtZ210L3YxYWxwaGExL2pvYi5wcm90bxINbWdtdC52MWFscGhhMSIuCg5HZXRKb2JzUmVxdWVzdBIcCgphY2NvdW50X2lkGAEgASgJQgi6SAVyA7ABASIzCg9HZXRKb2JzUmVzcG9uc2USIAoEam9icxgBIAMoCzISLm1nbXQudjFhbHBoYTEuSm9iIkUKCUpvYlNvdXJjZRI4CgdvcHRpb25zGAEgASgLMh8ubWdtdC52MWFscGhhMS5Kb2JTb3VyY2VPcHRpb25zQga6SAPIAQEioQQKEEpvYlNvdXJjZU9wdGlvbnMSQgoIcG9zdGdyZXMYASABKAsyLi5tZ210LnYxYWxwaGExLlBvc3RncmVzU291cmNlQ29ubmVjdGlvbk9wdGlvbnNIABI9CgZhd3NfczMYAiABKAsyKy5tZ210LnYxYWxwaGExLkF3c1MzU291cmNlQ29ubmVjdGlvbk9wdGlvbnNIABI8CgVteXNxbBgDIAEoCzIrLm1nbXQudjFhbHBoYTEuTXlzcWxTb3VyY2VDb25uZWN0aW9uT3B0aW9uc0gAEjgKCGdlbmVyYXRlGAQgASgLMiQubWdtdC52MWFscGhhMS5HZW5lcmF0ZVNvdXJjZU9wdGlvbnNIABI9CgthaV9nZW5lcmF0ZRgFIAEoCzImLm1nbXQudjFhbHBoYTEuQWlHZW5lcmF0ZVNvdXJjZU9wdGlvbnNIABJACgdtb25nb2RiGAYgASgLMi0ubWdtdC52MWFscGhhMS5Nb25nb0RCU291cmNlQ29ubmVjdGlvbk9wdGlvbnNIABJCCghkeW5hbW9kYhgHIAEoCzIuLm1nbXQudjFhbHBoYTEuRHluYW1vREJTb3VyY2VDb25uZWN0aW9uT3B0aW9uc0gAEjwKBW1zc3FsGAggASgLMisubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zSABCDwoGY29uZmlnEgW6SAIIASJuChRDcmVhdGVKb2JEZXN0aW5hdGlvbhIfCg1jb25uZWN0aW9uX2lkGAEgASgJQgi6SAVyA7ABARI1CgdvcHRpb25zGAIgASgLMiQubWdtdC52MWFscGhhMS5Kb2JEZXN0aW5hdGlvbk9wdGlvbnMidAoOSm9iRGVzdGluYXRpb24SHwoNY29ubmVjdGlvbl9pZBgBIAEoCUIIukgFcgOwAQESNQoHb3B0aW9ucxgCIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iRGVzdGluYXRpb25PcHRpb25zEgoKAmlkGAMgASgJIt0CChdBaUdlbmVyYXRlU291cmNlT3B0aW9ucxIiChBhaV9jb25uZWN0aW9uX2lkGAEgASgJQgi6SAVyA7ABARJGCgdzY2hlbWFzGAIgAygLMisubWdtdC52MWFscGhhMS5BaUdlbmVyYXRlU291cmNlU2NoZW1hT3B0aW9uQgi6SAWSAQIIARIuChdma19zb3VyY2VfY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQFIAIgBARIbCgptb2RlbF9uYW1lGAQgASgJQge6SARyAhABEhgKC3VzZXJfcHJvbXB0GAUgASgJSAGIAQESKwoTZ2VuZXJhdGVfYmF0Y2hfc2l6ZRgGIAEoA0IJukgGIgQYZCgBSAKIAQFCGgoYX2ZrX3NvdXJjZV9jb25uZWN0aW9uX2lkQg4KDF91c2VyX3Byb21wdEIWChRfZ2VuZXJhdGVfYmF0Y2hfc2l6ZSJ9ChxBaUdlbmVyYXRlU291cmNlU2NoZW1hT3B0aW9uEhcKBnNjaGVtYRgBIAEoCUIHukgEcgIQARJECgZ0YWJsZXMYAiADKAsyKi5tZ210LnYxYWxwaGExLkFpR2VuZXJhdGVTb3VyY2VUYWJsZU9wdGlvbkIIukgFkgECCAEiVAobQWlHZW5lcmF0ZVNvdXJjZVRhYmxlT3B0aW9uEhYKBXRhYmxlGAEgASgJQge6SARyAhABEh0KCXJvd19jb3VudBgCIAEoA0IKukgHIgUY6AcoASKvAQoVR2VuZXJhdGVTb3VyY2VPcHRpb25zEkQKB3NjaGVtYXMYASADKAsyKS5tZ210LnYxYWxwaGExLkdlbmVyYXRlU291cmNlU2NoZW1hT3B0aW9uQgi6SAWSAQIIARIuChdma19zb3VyY2VfY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQFIAIgBAUIaChhfZmtfc291cmNlX2Nvbm5lY3Rpb25faWRKBAgCEAMieQoaR2VuZXJhdGVTb3VyY2VTY2hlbWFPcHRpb24SFwoGc2NoZW1hGAEgASgJQge6SARyAhABEkIKBnRhYmxlcxgCIAMoCzIoLm1nbXQudjFhbHBoYTEuR2VuZXJhdGVTb3VyY2VUYWJsZU9wdGlvbkIIukgFkgECCAEiTwoZR2VuZXJhdGVTb3VyY2VUYWJsZU9wdGlvbhIWCgV0YWJsZRgBIAEoCUIHukgEcgIQARIaCglyb3dfY291bnQYAiABKANCB7pIBCICKAEiQQoeTW9uZ29EQlNvdXJjZUNvbm5lY3Rpb25PcHRpb25zEh8KDWNvbm5lY3Rpb25faWQYASABKAlCCLpIBXIDsAEBIu8BCh9EeW5hbW9EQlNvdXJjZUNvbm5lY3Rpb25PcHRpb25zEh8KDWNvbm5lY3Rpb25faWQYASABKAlCCLpIBXIDsAEBEjgKBnRhYmxlcxgCIAMoCzIoLm1nbXQudjFhbHBoYTEuRHluYW1vREJTb3VyY2VUYWJsZU9wdGlvbhJRChN1bm1hcHBlZF90cmFuc2Zvcm1zGAMgASgLMjQubWdtdC52MWFscGhhMS5EeW5hbW9EQlNvdXJjZVVubWFwcGVkVHJhbnNmb3JtQ29uZmlnEh4KFmVuYWJsZV9jb25zaXN0ZW50X3JlYWQYBCABKAgi/QEKJUR5bmFtb0RCU291cmNlVW5tYXBwZWRUcmFuc2Zvcm1Db25maWcSLwoBYhgBIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iTWFwcGluZ1RyYW5zZm9ybWVyEjUKB2Jvb2xlYW4YAiABKAsyJC5tZ210LnYxYWxwaGExLkpvYk1hcHBpbmdUcmFuc2Zvcm1lchIvCgFuGAQgASgLMiQubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nVHJhbnNmb3JtZXISLwoBcxgGIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iTWFwcGluZ1RyYW5zZm9ybWVySgQIAxAESgQIBRAGIl8KGUR5bmFtb0RCU291cmNlVGFibGVPcHRpb24SFgoFdGFibGUYASABKAlCB7pIBHICEAESGQoMd2hlcmVfY2xhdXNlGAIgASgJSACIAQFCDwoNX3doZXJlX2NsYXVzZSKeBwofUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucxI6CgdzY2hlbWFzGAIgAygLMikubWdtdC52MWFscGhhMS5Qb3N0Z3Jlc1NvdXJjZVNjaGVtYU9wdGlvbhIfCg1jb25uZWN0aW9uX2lkGAMgASgJQgi6SAVyA7ABARIpCiFzdWJzZXRfYnlfZm9yZWlnbl9rZXlfY29uc3RyYWludHMYBCABKAgSbgocbmV3X2NvbHVtbl9hZGRpdGlvbl9zdHJhdGVneRgFIAEoCzJILm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5OZXdDb2x1bW5BZGRpdGlvblN0cmF0ZWd5EmUKF2NvbHVtbl9yZW1vdmFsX3N0cmF0ZWd5GAYgASgLMkQubWdtdC52MWFscGhhMS5Qb3N0Z3Jlc1NvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneRqJAgoZTmV3Q29sdW1uQWRkaXRpb25TdHJhdGVneRJkCghoYWx0X2pvYhgBIAEoCzJQLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5OZXdDb2x1bW5BZGRpdGlvblN0cmF0ZWd5LkhhbHRKb2JIABJkCghhdXRvX21hcBgCIAEoCzJQLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5OZXdDb2x1bW5BZGRpdGlvblN0cmF0ZWd5LkF1dG9NYXBIABoJCgdIYWx0Sm9iGgkKB0F1dG9NYXBCCgoIc3RyYXRlZ3kaiQIKFUNvbHVtblJlbW92YWxTdHJhdGVneRJgCghoYWx0X2pvYhgBIAEoCzJMLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5Db2x1bW5SZW1vdmFsU3RyYXRlZ3kuSGFsdEpvYkgAEmgKDGNvbnRpbnVlX2pvYhgCIAEoCzJQLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucy5Db2x1bW5SZW1vdmFsU3RyYXRlZ3kuQ29udGludWVKb2JIABoJCgdIYWx0Sm9iGg0KC0NvbnRpbnVlSm9iQgoKCHN0cmF0ZWd5SgQIARACInkKGlBvc3RncmVzU291cmNlU2NoZW1hT3B0aW9uEhcKBnNjaGVtYRgBIAEoCUIHukgEcgIQARJCCgZ0YWJsZXMYAiADKAsyKC5tZ210LnYxYWxwaGExLlBvc3RncmVzU291cmNlVGFibGVPcHRpb25CCLpIBZIBAggBIl8KGVBvc3RncmVzU291cmNlVGFibGVPcHRpb24SFgoFdGFibGUYASABKAlCB7pIBHICEAESGQoMd2hlcmVfY2xhdXNlGAIgASgJSACIAQFCDwoNX3doZXJlX2NsYXVzZSKyBAocTXlzcWxTb3VyY2VDb25uZWN0aW9uT3B0aW9ucxIjChtoYWx0X29uX25ld19jb2x1bW5fYWRkaXRpb24YASABKAgSNwoHc2NoZW1hcxgCIAMoCzImLm1nbXQudjFhbHBoYTEuTXlzcWxTb3VyY2VTY2hlbWFPcHRpb24SHwoNY29ubmVjdGlvbl9pZBgDIAEoCUIIukgFcgOwAQESKQohc3Vic2V0X2J5X2ZvcmVpZ25fa2V5X2NvbnN0cmFpbnRzGAQgASgIEmIKF2NvbHVtbl9yZW1vdmFsX3N0cmF0ZWd5GAUgASgLMkEubWdtdC52MWFscGhhMS5NeXNxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneRqDAgoVQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5El0KCGhhbHRfam9iGAEgASgLMkkubWdtdC52MWFscGhhMS5NeXNxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneS5IYWx0Sm9iSAASZQoMY29udGludWVfam9iGAIgASgLMk0ubWdtdC52MWFscGhhMS5NeXNxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zLkNvbHVtblJlbW92YWxTdHJhdGVneS5Db250aW51ZUpvYkgAGgkKB0hhbHRKb2IaDQoLQ29udGludWVKb2JCCgoIc3RyYXRlZ3kicwoXTXlzcWxTb3VyY2VTY2hlbWFPcHRpb24SFwoGc2NoZW1hGAEgASgJQge6SARyAhABEj8KBnRhYmxlcxgCIAMoCzIlLm1nbXQudjFhbHBoYTEuTXlzcWxTb3VyY2VUYWJsZU9wdGlvbkIIukgFkgECCAEiXAoWTXlzcWxTb3VyY2VUYWJsZU9wdGlvbhIWCgV0YWJsZRgBIAEoCUIHukgEcgIQARIZCgx3aGVyZV9jbGF1c2UYAiABKAlIAIgBAUIPCg1fd2hlcmVfY2xhdXNlIrIEChxNc3NxbFNvdXJjZUNvbm5lY3Rpb25PcHRpb25zEiMKG2hhbHRfb25fbmV3X2NvbHVtbl9hZGRpdGlvbhgBIAEoCBI3CgdzY2hlbWFzGAIgAygLMiYubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZVNjaGVtYU9wdGlvbhIfCg1jb25uZWN0aW9uX2lkGAMgASgJQgi6SAVyA7ABARIpCiFzdWJzZXRfYnlfZm9yZWlnbl9rZXlfY29uc3RyYWludHMYBCABKAgSYgoXY29sdW1uX3JlbW92YWxfc3RyYXRlZ3kYBSABKAsyQS5tZ210LnYxYWxwaGExLk1zc3FsU291cmNlQ29ubmVjdGlvbk9wdGlvbnMuQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5GoMCChVDb2x1bW5SZW1vdmFsU3RyYXRlZ3kSXQoIaGFsdF9qb2IYASABKAsySS5tZ210LnYxYWxwaGExLk1zc3FsU291cmNlQ29ubmVjdGlvbk9wdGlvbnMuQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5LkhhbHRKb2JIABJlCgxjb250aW51ZV9qb2IYAiABKAsyTS5tZ210LnYxYWxwaGExLk1zc3FsU291cmNlQ29ubmVjdGlvbk9wdGlvbnMuQ29sdW1uUmVtb3ZhbFN0cmF0ZWd5LkNvbnRpbnVlSm9iSAAaCQoHSGFsdEpvYhoNCgtDb250aW51ZUpvYkIKCghzdHJhdGVneSJzChdNc3NxbFNvdXJjZVNjaGVtYU9wdGlvbhIXCgZzY2hlbWEYASABKAlCB7pIBHICEAESPwoGdGFibGVzGAIgAygLMiUubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZVRhYmxlT3B0aW9uQgi6SAWSAQIIASJcChZNc3NxbFNvdXJjZVRhYmxlT3B0aW9uEhYKBXRhYmxlGAEgASgJQge6SARyAhABEhkKDHdoZXJlX2NsYXVzZRgCIAEoCUgAiAEBQg8KDV93aGVyZV9jbGF1c2UiPwocQXdzUzNTb3VyY2VDb25uZWN0aW9uT3B0aW9ucxIfCg1jb25uZWN0aW9uX2lkGAEgASgJQgi6SAVyA7ABASLbBAoVSm9iRGVzdGluYXRpb25PcHRpb25zEk8KEHBvc3RncmVzX29wdGlvbnMYASABKAsyMy5tZ210LnYxYWxwaGExLlBvc3RncmVzRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9uc0gAEkoKDmF3c19zM19vcHRpb25zGAIgASgLMjAubWdtdC52MWFscGhhMS5Bd3NTM0Rlc3RpbmF0aW9uQ29ubmVjdGlvbk9wdGlvbnNIABJJCg1teXNxbF9vcHRpb25zGAMgASgLMjAubWdtdC52MWFscGhhMS5NeXNxbERlc3RpbmF0aW9uQ29ubmVjdGlvbk9wdGlvbnNIABJNCg9tb25nb2RiX29wdGlvbnMYBCABKAsyMi5tZ210LnYxYWxwaGExLk1vbmdvREJEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSAASXgoYZ2NwX2Nsb3Vkc3RvcmFnZV9vcHRpb25zGAUgASgLMjoubWdtdC52MWFscGhhMS5HY3BDbG91ZFN0b3JhZ2VEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSAASTwoQZHluYW1vZGJfb3B0aW9ucxgGIAEoCzIzLm1nbXQudjFhbHBoYTEuRHluYW1vREJEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSAASSQoNbXNzcWxfb3B0aW9ucxgHIAEoCzIwLm1nbXQudjFhbHBoYTEuTXNzcWxEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zSABCDwoGY29uZmlnEgW6SAIIASIlCiNNb25nb0RCRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucyItCitHY3BDbG91ZFN0b3JhZ2VEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zIm4KJER5bmFtb0RCRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucxJGCg50YWJsZV9tYXBwaW5ncxgBIAMoCzIuLm1nbXQudjFhbHBoYTEuRHluYW1vREJEZXN0aW5hdGlvblRhYmxlTWFwcGluZyJSCh9EeW5hbW9EQkRlc3RpbmF0aW9uVGFibGVNYXBwaW5nEhQKDHNvdXJjZV90YWJsZRgBIAEoCRIZChFkZXN0aW5hdGlvbl90YWJsZRgCIAEoCSLKAgokUG9zdGdyZXNEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zEkIKDnRydW5jYXRlX3RhYmxlGAEgASgLMioubWdtdC52MWFscGhhMS5Qb3N0Z3Jlc1RydW5jYXRlVGFibGVDb25maWcSGQoRaW5pdF90YWJsZV9zY2hlbWEYAiABKAgSPAoLb25fY29uZmxpY3QYAyABKAsyJy5tZ210LnYxYWxwaGExLlBvc3RncmVzT25Db25mbGljdENvbmZpZxIjChtza2lwX2ZvcmVpZ25fa2V5X3Zpb2xhdGlvbnMYBCABKAgSKQoFYmF0Y2gYBSABKAsyGi5tZ210LnYxYWxwaGExLkJhdGNoQ29uZmlnEiMKDW1heF9pbl9mbGlnaHQYBiABKA1CB7pIBCoCKAFIAIgBAUIQCg5fbWF4X2luX2ZsaWdodCKoAgoYUG9zdGdyZXNPbkNvbmZsaWN0Q29uZmlnEhIKCmRvX25vdGhpbmcYASABKAgSVgoHbm90aGluZxgCIAEoCzJDLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNPbkNvbmZsaWN0Q29uZmlnLlBvc3RncmVzT25Db25mbGljdERvTm90aGluZ0gAElIKBnVwZGF0ZRgDIAEoCzJALm1nbXQudjFhbHBoYTEuUG9zdGdyZXNPbkNvbmZsaWN0Q29uZmlnLlBvc3RncmVzT25Db25mbGljdFVwZGF0ZUgAGh0KG1Bvc3RncmVzT25Db25mbGljdERvTm90aGluZxoaChhQb3N0Z3Jlc09uQ29uZmxpY3RVcGRhdGVCEQoIc3RyYXRlZ3kSBbpIAggAIk4KG1Bvc3RncmVzVHJ1bmNhdGVUYWJsZUNvbmZpZxIeChZ0cnVuY2F0ZV9iZWZvcmVfaW5zZXJ0GAEgASgIEg8KB2Nhc2NhZGUYAiABKAgiwQIKIU15c3FsRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucxI/Cg50cnVuY2F0ZV90YWJsZRgBIAEoCzInLm1nbXQudjFhbHBoYTEuTXlzcWxUcnVuY2F0ZVRhYmxlQ29uZmlnEhkKEWluaXRfdGFibGVfc2NoZW1hGAIgASgIEjkKC29uX2NvbmZsaWN0GAMgASgLMiQubWdtdC52MWFscGhhMS5NeXNxbE9uQ29uZmxpY3RDb25maWcSIwobc2tpcF9mb3JlaWduX2tleV92aW9sYXRpb25zGAQgASgIEikKBWJhdGNoGAUgASgLMhoubWdtdC52MWFscGhhMS5CYXRjaENvbmZpZxIjCg1tYXhfaW5fZmxpZ2h0GAYgASgNQge6SAQqAigBSACIAQFCEAoOX21heF9pbl9mbGlnaHQiOgoYTXlzcWxUcnVuY2F0ZVRhYmxlQ29uZmlnEh4KFnRydW5jYXRlX2JlZm9yZV9pbnNlcnQYASABKAgikwIKFU15c3FsT25Db25mbGljdENvbmZpZxISCgpkb19ub3RoaW5nGAEgASgIElAKB25vdGhpbmcYAiABKAsyPS5tZ210LnYxYWxwaGExLk15c3FsT25Db25mbGljdENvbmZpZy5NeXNxbE9uQ29uZmxpY3REb05vdGhpbmdIABJMCgZ1cGRhdGUYAyABKAsyOi5tZ210LnYxYWxwaGExLk15c3FsT25Db25mbGljdENvbmZpZy5NeXNxbE9uQ29uZmxpY3RVcGRhdGVIABoaChhNeXNxbE9uQ29uZmxpY3REb05vdGhpbmcaFwoVTXlzcWxPbkNvbmZsaWN0VXBkYXRlQhEKCHN0cmF0ZWd5EgW6SAIIACLBAgohTXNzcWxEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zEj8KDnRydW5jYXRlX3RhYmxlGAEgASgLMicubWdtdC52MWFscGhhMS5Nc3NxbFRydW5jYXRlVGFibGVDb25maWcSGQoRaW5pdF90YWJsZV9zY2hlbWEYAiABKAgSOQoLb25fY29uZmxpY3QYAyABKAsyJC5tZ210LnYxYWxwaGExLk1zc3FsT25Db25mbGljdENvbmZpZxIjChtza2lwX2ZvcmVpZ25fa2V5X3Zpb2xhdGlvbnMYBCABKAgSKQoFYmF0Y2gYBSABKAsyGi5tZ210LnYxYWxwaGExLkJhdGNoQ29uZmlnEiMKDW1heF9pbl9mbGlnaHQYBiABKA1CB7pIBCoCKAFIAIgBAUIQCg5fbWF4X2luX2ZsaWdodCI6ChhNc3NxbFRydW5jYXRlVGFibGVDb25maWcSHgoWdHJ1bmNhdGVfYmVmb3JlX2luc2VydBgBIAEoCCIrChVNc3NxbE9uQ29uZmxpY3RDb25maWcSEgoKZG9fbm90aGluZxgBIAEoCCKOBAohQXdzUzNEZXN0aW5hdGlvbkNvbm5lY3Rpb25PcHRpb25zElQKDXN0b3JhZ2VfY2xhc3MYASABKA4yPS5tZ210LnYxYWxwaGExLkF3c1MzRGVzdGluYXRpb25Db25uZWN0aW9uT3B0aW9ucy5TdG9yYWdlQ2xhc3MSIwoNbWF4X2luX2ZsaWdodBgCIAEoDUIHukgEKgIoAUgAiAEBEhQKB3RpbWVvdXQYAyABKAlIAYgBARIpCgViYXRjaBgEIAEoCzIaLm1nbXQudjFhbHBoYTEuQmF0Y2hDb25maWcijgIKDFN0b3JhZ2VDbGFzcxIdChlTVE9SQUdFX0NMQVNTX1VOU1BFQ0lGSUVEEAASGgoWU1RPUkFHRV9DTEFTU19TVEFOREFSRBABEiQKIFNUT1JBR0VfQ0xBU1NfUkVEVUNFRF9SRURVTkRBTkNZEAISGQoVU1RPUkFHRV9DTEFTU19HTEFDSUVSEAMSHQoZU1RPUkFHRV9DTEFTU19TVEFOREFSRF9JQRAEEhwKGFNUT1JBR0VfQ0xBU1NfT05FWk9ORV9JQRAFEiUKIVNUT1JBR0VfQ0xBU1NfSU5URUxMSUdFTlRfVElFUklORxAGEh4KGlNUT1JBR0VfQ0xBU1NfREVFUF9BUkNISVZFEAdCEAoOX21heF9pbl9mbGlnaHRCCgoIX3RpbWVvdXQiSwoLQmF0Y2hDb25maWcSEgoFY291bnQYASABKA1IAIgBARITCgZwZXJpb2QYAiABKAlIAYgBAUIICgZfY291bnRCCQoHX3BlcmlvZCLuAwoQQ3JlYXRlSm9iUmVxdWVzdBIcCgphY2NvdW50X2lkGAEgASgJQgi6SAVyA7ABARIrCghqb2JfbmFtZRgCIAEoCUIZukgWchQyEl5bYS16MC05LV17MywxMDB9JBIaCg1jcm9uX3NjaGVkdWxlGAMgASgJSACIAQESKwoIbWFwcGluZ3MYBCADKAsyGS5tZ210LnYxYWxwaGExLkpvYk1hcHBpbmcSKAoGc291cmNlGAUgASgLMhgubWdtdC52MWFscGhhMS5Kb2JTb3VyY2USOQoMZGVzdGluYXRpb25zGAYgAygLMiMubWdtdC52MWFscGhhMS5DcmVhdGVKb2JEZXN0aW5hdGlvbhIYChBpbml0aWF0ZV9qb2JfcnVuGAcgASgIEjgKEHdvcmtmbG93X29wdGlvbnMYCCABKAsyHi5tZ210LnYxYWxwaGExLldvcmtmbG93T3B0aW9ucxI0CgxzeW5jX29wdGlvbnMYCSABKAsyHi5tZ210LnYxYWxwaGExLkFjdGl2aXR5T3B0aW9ucxJFChR2aXJ0dWFsX2ZvcmVpZ25fa2V5cxgKIAMoCzInLm1nbXQudjFhbHBoYTEuVmlydHVhbEZvcmVpZ25Db25zdHJhaW50QhAKDl9jcm9uX3NjaGVkdWxlImUKD1dvcmtmbG93T3B0aW9ucxIYCgtydW5fdGltZW91dBgIIAEoA0gAiAEBQg4KDF9ydW5fdGltZW91dEoECAEQAkoECAIQA0oECAMQBEoECAQQBUoECAUQBkoECAYQB0oECAcQCCLbAQoPQWN0aXZpdHlPcHRpb25zEi8KGXNjaGVkdWxlX3RvX2Nsb3NlX3RpbWVvdXQYASABKANCB7pIBCICKAFIAIgBARIsChZzdGFydF90b19jbG9zZV90aW1lb3V0GAIgASgDQge6SAQiAigBSAGIAQESMAoMcmV0cnlfcG9saWN5GAMgASgLMhoubWdtdC52MWFscGhhMS5SZXRyeVBvbGljeUIcChpfc2NoZWR1bGVfdG9fY2xvc2VfdGltZW91dEIZChdfc3RhcnRfdG9fY2xvc2VfdGltZW91dCJKCgtSZXRyeVBvbGljeRImChBtYXhpbXVtX2F0dGVtcHRzGAEgASgFQge6SAQaAigASACIAQFCEwoRX21heGltdW1fYXR0ZW1wdHMiNAoRQ3JlYXRlSm9iUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IiTwoVSm9iTWFwcGluZ1RyYW5zZm9ybWVyEjAKBmNvbmZpZxgDIAEoCzIgLm1nbXQudjFhbHBoYTEuVHJhbnNmb3JtZXJDb25maWdKBAgBEAIikQEKCkpvYk1hcHBpbmcSFwoGc2NoZW1hGAEgASgJQge6SARyAhABEhYKBXRhYmxlGAIgASgJQge6SARyAhABEhcKBmNvbHVtbhgDIAEoCUIHukgEcgIQARI5Cgt0cmFuc2Zvcm1lchgFIAEoCzIkLm1nbXQudjFhbHBoYTEuSm9iTWFwcGluZ1RyYW5zZm9ybWVyIiUKDUdldEpvYlJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIjEKDkdldEpvYlJlc3BvbnNlEh8KA2pvYhgBIAEoCzISLm1nbXQudjFhbHBoYTEuSm9iIl4KGFVwZGF0ZUpvYlNjaGVkdWxlUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESGgoNY3Jvbl9zY2hlZHVsZRgCIAEoCUgAiAEBQhAKDl9jcm9uX3NjaGVkdWxlIjwKGVVwZGF0ZUpvYlNjaGVkdWxlUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IiUgoPUGF1c2VKb2JSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABARINCgVwYXVzZRgCIAEoCBIRCgRub3RlGAMgASgJSACIAQFCBwoFX25vdGUiMwoQUGF1c2VKb2JSZXNwb25zZRIfCgNqb2IYASABKAsyEi5tZ210LnYxYWxwaGExLkpvYiLWAQogVXBkYXRlSm9iU291cmNlQ29ubmVjdGlvblJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEigKBnNvdXJjZRgCIAEoCzIYLm1nbXQudjFhbHBoYTEuSm9iU291cmNlEisKCG1hcHBpbmdzGAMgAygLMhkubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nEkUKFHZpcnR1YWxfZm9yZWlnbl9rZXlzGAQgAygLMicubWdtdC52MWFscGhhMS5WaXJ0dWFsRm9yZWlnbkNvbnN0cmFpbnQiRAohVXBkYXRlSm9iU291cmNlQ29ubmVjdGlvblJlc3BvbnNlEh8KA2pvYhgBIAEoCzISLm1nbXQudjFhbHBoYTEuSm9iImEKGlBvc3RncmVzU291cmNlU2NoZW1hU3Vic2V0EkMKEHBvc3RncmVzX3NjaGVtYXMYASADKAsyKS5tZ210LnYxYWxwaGExLlBvc3RncmVzU291cmNlU2NoZW1hT3B0aW9uIlgKF015c3FsU291cmNlU2NoZW1hU3Vic2V0Ej0KDW15c3FsX3NjaGVtYXMYASADKAsyJi5tZ210LnYxYWxwaGExLk15c3FsU291cmNlU2NoZW1hT3B0aW9uIlYKGkR5bmFtb0RCU291cmNlU2NoZW1hU3Vic2V0EjgKBnRhYmxlcxgBIAMoCzIoLm1nbXQudjFhbHBoYTEuRHluYW1vREJTb3VyY2VUYWJsZU9wdGlvbiJYChdNc3NxbFNvdXJjZVNjaGVtYVN1YnNldBI9Cg1tc3NxbF9zY2hlbWFzGAEgAygLMiYubWdtdC52MWFscGhhMS5Nc3NxbFNvdXJjZVNjaGVtYU9wdGlvbiK+AgoYSm9iU291cmNlU3FsU3ViZXRTY2hlbWFzEkQKD3Bvc3RncmVzX3N1YnNldBgCIAEoCzIpLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNTb3VyY2VTY2hlbWFTdWJzZXRIABI+CgxteXNxbF9zdWJzZXQYAyABKAsyJi5tZ210LnYxYWxwaGExLk15c3FsU291cmNlU2NoZW1hU3Vic2V0SAASRAoPZHluYW1vZGJfc3Vic2V0GAQgASgLMikubWdtdC52MWFscGhhMS5EeW5hbW9EQlNvdXJjZVNjaGVtYVN1YnNldEgAEj4KDG1zc3FsX3N1YnNldBgFIAEoCzImLm1nbXQudjFhbHBoYTEuTXNzcWxTb3VyY2VTY2hlbWFTdWJzZXRIAEIQCgdzY2hlbWFzEgW6SAIIAUoECAEQAiKkAQonU2V0Sm9iU291cmNlU3FsQ29ubmVjdGlvblN1YnNldHNSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABARI4CgdzY2hlbWFzGAIgASgLMicubWdtdC52MWFscGhhMS5Kb2JTb3VyY2VTcWxTdWJldFNjaGVtYXMSKQohc3Vic2V0X2J5X2ZvcmVpZ25fa2V5X2NvbnN0cmFpbnRzGAMgASgIIksKKFNldEpvYlNvdXJjZVNxbENvbm5lY3Rpb25TdWJzZXRzUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IisQEKJVVwZGF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvblJlcXVlc3QSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARIfCg1jb25uZWN0aW9uX2lkGAIgASgJQgi6SAVyA7ABARI1CgdvcHRpb25zGAMgASgLMiQubWdtdC52MWFscGhhMS5Kb2JEZXN0aW5hdGlvbk9wdGlvbnMSFgoOZGVzdGluYXRpb25faWQYBCABKAkiSQomVXBkYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IiSQolRGVsZXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVxdWVzdBIgCg5kZXN0aW5hdGlvbl9pZBgBIAEoCUIIukgFcgOwAQEiKAomRGVsZXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uUmVzcG9uc2UifQomQ3JlYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uc1JlcXVlc3QSGAoGam9iX2lkGAEgASgJQgi6SAVyA7ABARI5CgxkZXN0aW5hdGlvbnMYAiADKAsyIy5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYkRlc3RpbmF0aW9uIkoKJ0NyZWF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvbnNSZXNwb25zZRIfCgNqb2IYASABKAsyEi5tZ210LnYxYWxwaGExLkpvYiIoChBEZWxldGVKb2JSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASITChFEZWxldGVKb2JSZXNwb25zZSJiChlJc0pvYk5hbWVBdmFpbGFibGVSZXF1ZXN0EicKBG5hbWUYASABKAlCGbpIFnIUMhJeW2EtejAtOS1dezMsMTAwfSQSHAoKYWNjb3VudF9pZBgCIAEoCUIIukgFcgOwAQEiMgoaSXNKb2JOYW1lQXZhaWxhYmxlUmVzcG9uc2USFAoMaXNfYXZhaWxhYmxlGAEgASgIIlUKEUdldEpvYlJ1bnNSZXF1ZXN0EhoKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQFIABIeCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABAUgAQgQKAmlkIj0KEkdldEpvYlJ1bnNSZXNwb25zZRInCghqb2JfcnVucxgBIAMoCzIVLm1nbXQudjFhbHBoYTEuSm9iUnVuIkQKEEdldEpvYlJ1blJlcXVlc3QSEgoKam9iX3J1bl9pZBgBIAEoCRIcCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABASI7ChFHZXRKb2JSdW5SZXNwb25zZRImCgdqb2JfcnVuGAEgASgLMhUubWdtdC52MWFscGhhMS5Kb2JSdW4iLwoTQ3JlYXRlSm9iUnVuUmVxdWVzdBIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBIhYKFENyZWF0ZUpvYlJ1blJlc3BvbnNlIkcKE0NhbmNlbEpvYlJ1blJlcXVlc3QSEgoKam9iX3J1bl9pZBgBIAEoCRIcCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABASIWChRDYW5jZWxKb2JSdW5SZXNwb25zZSK8BAoDSm9iEgoKAmlkGAEgASgJEhoKEmNyZWF0ZWRfYnlfdXNlcl9pZBgCIAEoCRIuCgpjcmVhdGVkX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIaChJ1cGRhdGVkX2J5X3VzZXJfaWQYBCABKAkSLgoKdXBkYXRlZF9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDAoEbmFtZRgGIAEoCRIoCgZzb3VyY2UYByABKAsyGC5tZ210LnYxYWxwaGExLkpvYlNvdXJjZRIzCgxkZXN0aW5hdGlvbnMYCCADKAsyHS5tZ210LnYxYWxwaGExLkpvYkRlc3RpbmF0aW9uEisKCG1hcHBpbmdzGAkgAygLMhkubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nEhoKDWNyb25fc2NoZWR1bGUYCiABKAlIAIgBARISCgphY2NvdW50X2lkGAsgASgJEjQKDHN5bmNfb3B0aW9ucxgMIAEoCzIeLm1nbXQudjFhbHBoYTEuQWN0aXZpdHlPcHRpb25zEjgKEHdvcmtmbG93X29wdGlvbnMYDSABKAsyHi5tZ210LnYxYWxwaGExLldvcmtmbG93T3B0aW9ucxJFChR2aXJ0dWFsX2ZvcmVpZ25fa2V5cxgOIAMoCzInLm1nbXQudjFhbHBoYTEuVmlydHVhbEZvcmVpZ25Db25zdHJhaW50QhAKDl9jcm9uX3NjaGVkdWxlIlIKDEpvYlJlY2VudFJ1bhIuCgpzdGFydF90aW1lGAEgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBISCgpqb2JfcnVuX2lkGAIgASgJIjMKF0dldEpvYlJlY2VudFJ1bnNSZXF1ZXN0EhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQEiTAoYR2V0Sm9iUmVjZW50UnVuc1Jlc3BvbnNlEjAKC3JlY2VudF9ydW5zGAEgAygLMhsubWdtdC52MWFscGhhMS5Kb2JSZWNlbnRSdW4iQQoLSm9iTmV4dFJ1bnMSMgoObmV4dF9ydW5fdGltZXMYASADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIjEKFUdldEpvYk5leHRSdW5zUmVxdWVzdBIYCgZqb2JfaWQYASABKAlCCLpIBXIDsAEBIkcKFkdldEpvYk5leHRSdW5zUmVzcG9uc2USLQoJbmV4dF9ydW5zGAEgASgLMhoubWdtdC52MWFscGhhMS5Kb2JOZXh0UnVucyIvChNHZXRKb2JTdGF0dXNSZXF1ZXN0EhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQEiQAoUR2V0Sm9iU3RhdHVzUmVzcG9uc2USKAoGc3RhdHVzGAEgASgOMhgubWdtdC52MWFscGhhMS5Kb2JTdGF0dXMiVQoPSm9iU3RhdHVzUmVjb3JkEhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQESKAoGc3RhdHVzGAIgASgOMhgubWdtdC52MWFscGhhMS5Kb2JTdGF0dXMiNQoVR2V0Sm9iU3RhdHVzZXNSZXF1ZXN0EhwKCmFjY291bnRfaWQYASABKAlCCLpIBXIDsAEBIkoKFkdldEpvYlN0YXR1c2VzUmVzcG9uc2USMAoIc3RhdHVzZXMYASADKAsyHi5tZ210LnYxYWxwaGExLkpvYlN0YXR1c1JlY29yZCIiCg9BY3Rpdml0eUZhaWx1cmUSDwoHbWVzc2FnZRgBIAEoCSKjAQoPUGVuZGluZ0FjdGl2aXR5Ei0KBnN0YXR1cxgBIAEoDjIdLm1nbXQudjFhbHBoYTEuQWN0aXZpdHlTdGF0dXMSFQoNYWN0aXZpdHlfbmFtZRgCIAEoCRI5CgxsYXN0X2ZhaWx1cmUYAyABKAsyHi5tZ210LnYxYWxwaGExLkFjdGl2aXR5RmFpbHVyZUgAiAEBQg8KDV9sYXN0X2ZhaWx1cmUimQIKBkpvYlJ1bhIKCgJpZBgBIAEoCRIOCgZqb2JfaWQYAiABKAkSDAoEbmFtZRgDIAEoCRIrCgZzdGF0dXMYBCABKA4yGy5tZ210LnYxYWxwaGExLkpvYlJ1blN0YXR1cxIuCgpzdGFydGVkX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI1Cgxjb21wbGV0ZWRfYXQYByABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSACIAQESOgoScGVuZGluZ19hY3Rpdml0aWVzGAggAygLMh4ubWdtdC52MWFscGhhMS5QZW5kaW5nQWN0aXZpdHlCDwoNX2NvbXBsZXRlZF9hdEoECAUQBiI8ChRKb2JSdW5FdmVudFRhc2tFcnJvchIPCgdtZXNzYWdlGAEgASgJEhMKC3JldHJ5X3N0YXRlGAIgASgJIo8BCg9Kb2JSdW5FdmVudFRhc2sSCgoCaWQYASABKAMSDAoEdHlwZRgCIAEoCRIuCgpldmVudF90aW1lGAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIyCgVlcnJvchgEIAEoCzIjLm1nbXQudjFhbHBoYTEuSm9iUnVuRXZlbnRUYXNrRXJyb3IiMwoSSm9iUnVuU3luY01ldGFkYXRhEg4KBnNjaGVtYRgBIAEoCRINCgV0YWJsZRgCIAEoCSJkChNKb2JSdW5FdmVudE1ldGFkYXRhEjoKDXN5bmNfbWV0YWRhdGEYASABKAsyIS5tZ210LnYxYWxwaGExLkpvYlJ1blN5bmNNZXRhZGF0YUgAQhEKCG1ldGFkYXRhEgW6SAIIASLsAQoLSm9iUnVuRXZlbnQSCgoCaWQYASABKAMSDAoEdHlwZRgCIAEoCRIuCgpzdGFydF90aW1lGAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgpjbG9zZV90aW1lGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI0CghtZXRhZGF0YRgFIAEoCzIiLm1nbXQudjFhbHBoYTEuSm9iUnVuRXZlbnRNZXRhZGF0YRItCgV0YXNrcxgGIAMoCzIeLm1nbXQudjFhbHBoYTEuSm9iUnVuRXZlbnRUYXNrIkoKFkdldEpvYlJ1bkV2ZW50c1JlcXVlc3QSEgoKam9iX3J1bl9pZBgBIAEoCRIcCgphY2NvdW50X2lkGAIgASgJQgi6SAVyA7ABASJeChdHZXRKb2JSdW5FdmVudHNSZXNwb25zZRIqCgZldmVudHMYASADKAsyGi5tZ210LnYxYWxwaGExLkpvYlJ1bkV2ZW50EhcKD2lzX3J1bl9jb21wbGV0ZRgCIAEoCCJHChNEZWxldGVKb2JSdW5SZXF1ZXN0EhIKCmpvYl9ydW5faWQYASABKAkSHAoKYWNjb3VudF9pZBgCIAEoCUIIukgFcgOwAQEiFgoURGVsZXRlSm9iUnVuUmVzcG9uc2UiSgoWVGVybWluYXRlSm9iUnVuUmVxdWVzdBISCgpqb2JfcnVuX2lkGAEgASgJEhwKCmFjY291bnRfaWQYAiABKAlCCLpIBXIDsAEBIhkKF1Rlcm1pbmF0ZUpvYlJ1blJlc3BvbnNlIvEBChpHZXRKb2JSdW5Mb2dzU3RyZWFtUmVxdWVzdBISCgpqb2JfcnVuX2lkGAEgASgJEhwKCmFjY291bnRfaWQYAiABKAlCCLpIBXIDsAEBEigKBndpbmRvdxgDIAEoDjIYLm1nbXQudjFhbHBoYTEuTG9nV2luZG93EhMKC3Nob3VsZF90YWlsGAQgASgIEiMKDW1heF9sb2dfbGluZXMYBSABKANCB7pIBCICKAFIAIgBARIrCgpsb2dfbGV2ZWxzGAYgAygOMhcubWdtdC52MWFscGhhMS5Mb2dMZXZlbEIQCg5fbWF4X2xvZ19saW5lcyJxChtHZXRKb2JSdW5Mb2dzU3RyZWFtUmVzcG9uc2USEAoIbG9nX2xpbmUYASABKAkSMgoJdGltZXN0YW1wGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEgAiAEBQgwKCl90aW1lc3RhbXAi1gEKFEdldEpvYlJ1bkxvZ3NSZXF1ZXN0EhIKCmpvYl9ydW5faWQYASABKAkSHAoKYWNjb3VudF9pZBgCIAEoCUIIukgFcgOwAQESKAoGd2luZG93GAMgASgOMhgubWdtdC52MWFscGhhMS5Mb2dXaW5kb3cSIwoNbWF4X2xvZ19saW5lcxgEIAEoA0IHukgEIgIoAUgAiAEBEisKCmxvZ19sZXZlbHMYBSADKA4yFy5tZ210LnYxYWxwaGExLkxvZ0xldmVsQhAKDl9tYXhfbG9nX2xpbmVzIrcBChVHZXRKb2JSdW5Mb2dzUmVzcG9uc2USPwoJbG9nX2xpbmVzGAEgAygLMiwubWdtdC52MWFscGhhMS5HZXRKb2JSdW5Mb2dzUmVzcG9uc2UuTG9nTGluZRpdCgdMb2dMaW5lEhAKCGxvZ19saW5lGAEgASgJEjIKCXRpbWVzdGFtcBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBAUIMCgpfdGltZXN0YW1wIm4KHFNldEpvYldvcmtmbG93T3B0aW9uc1JlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEjgKEHdvcmZrbG93X29wdGlvbnMYAiABKAsyHi5tZ210LnYxYWxwaGExLldvcmtmbG93T3B0aW9ucyJACh1TZXRKb2JXb3JrZmxvd09wdGlvbnNSZXNwb25zZRIfCgNqb2IYASABKAsyEi5tZ210LnYxYWxwaGExLkpvYiJmChhTZXRKb2JTeW5jT3B0aW9uc1JlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEjQKDHN5bmNfb3B0aW9ucxgCIAEoCzIeLm1nbXQudjFhbHBoYTEuQWN0aXZpdHlPcHRpb25zIjwKGVNldEpvYlN5bmNPcHRpb25zUmVzcG9uc2USHwoDam9iGAEgASgLMhIubWdtdC52MWFscGhhMS5Kb2IikQIKGlZhbGlkYXRlSm9iTWFwcGluZ3NSZXF1ZXN0EhwKCmFjY291bnRfaWQYASABKAlCCLpIBXIDsAEBEisKCG1hcHBpbmdzGAIgAygLMhkubWdtdC52MWFscGhhMS5Kb2JNYXBwaW5nEh8KDWNvbm5lY3Rpb25faWQYAyABKAlCCLpIBXIDsAEBEkUKFHZpcnR1YWxfZm9yZWlnbl9rZXlzGAQgAygLMicubWdtdC52MWFscGhhMS5WaXJ0dWFsRm9yZWlnbkNvbnN0cmFpbnQSMQoKam9iX3NvdXJjZRgFIAEoCzIYLm1nbXQudjFhbHBoYTEuSm9iU291cmNlSACIAQFCDQoLX2pvYl9zb3VyY2UiTAoLQ29sdW1uRXJyb3ISDgoGc2NoZW1hGAEgASgJEg0KBXRhYmxlGAIgASgJEg4KBmNvbHVtbhgDIAEoCRIOCgZlcnJvcnMYBCADKAkiUAoNQ29sdW1uV2FybmluZxIOCgZzY2hlbWEYASABKAkSDQoFdGFibGUYAiABKAkSDgoGY29sdW1uGAMgASgJEhAKCHdhcm5pbmdzGAUgAygJIh8KDURhdGFiYXNlRXJyb3ISDgoGZXJyb3JzGAEgAygJIr4BChtWYWxpZGF0ZUpvYk1hcHBpbmdzUmVzcG9uc2USMQoNY29sdW1uX2Vycm9ycxgBIAMoCzIaLm1nbXQudjFhbHBoYTEuQ29sdW1uRXJyb3ISNQoPZGF0YWJhc2VfZXJyb3JzGAIgASgLMhwubWdtdC52MWFscGhhMS5EYXRhYmFzZUVycm9yEjUKD2NvbHVtbl93YXJuaW5ncxgDIAMoCzIcLm1nbXQudjFhbHBoYTEuQ29sdW1uV2FybmluZyJDChFWaXJ0dWFsRm9yZWlnbktleRIOCgZzY2hlbWEYASABKAkSDQoFdGFibGUYAiABKAkSDwoHY29sdW1ucxgDIAMoCSKBAQoYVmlydHVhbEZvcmVpZ25Db25zdHJhaW50Eg4KBnNjaGVtYRgBIAEoCRINCgV0YWJsZRgCIAEoCRIPCgdjb2x1bW5zGAMgAygJEjUKC2ZvcmVpZ25fa2V5GAQgASgLMiAubWdtdC52MWFscGhhMS5WaXJ0dWFsRm9yZWlnbktleSJnCg1SdW5Db250ZXh0S2V5EhsKCmpvYl9ydW5faWQYASABKAlCB7pIBHICEAESHAoLZXh0ZXJuYWxfaWQYAiABKAlCB7pIBHICEAESGwoKYWNjb3VudF9pZBgDIAEoCUIHukgEcgIQASJAChRHZXRSdW5Db250ZXh0UmVxdWVzdBIoCgJpZBgBIAEoCzIcLm1nbXQudjFhbHBoYTEuUnVuQ29udGV4dEtleSImChVHZXRSdW5Db250ZXh0UmVzcG9uc2USDQoFdmFsdWUYASABKAwiTwoUU2V0UnVuQ29udGV4dFJlcXVlc3QSKAoCaWQYASABKAsyHC5tZ210LnYxYWxwaGExLlJ1bkNvbnRleHRLZXkSDQoFdmFsdWUYAiABKAwiFwoVU2V0UnVuQ29udGV4dFJlc3BvbnNlIlAKFVNldFJ1bkNvbnRleHRzUmVxdWVzdBIoCgJpZBgBIAEoCzIcLm1nbXQudjFhbHBoYTEuUnVuQ29udGV4dEtleRINCgV2YWx1ZRgCIAEoDCIYChZTZXRSdW5Db250ZXh0c1Jlc3BvbnNlIrwCCgdKb2JIb29rEgoKAmlkGAEgASgJEgwKBG5hbWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSDgoGam9iX2lkGAQgASgJEiwKBmNvbmZpZxgFIAEoCzIcLm1nbXQudjFhbHBoYTEuSm9iSG9va0NvbmZpZxIaChJjcmVhdGVkX2J5X3VzZXJfaWQYBiABKAkSLgoKY3JlYXRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGgoSdXBkYXRlZF9ieV91c2VyX2lkGAggASgJEi4KCnVwZGF0ZWRfYXQYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEg8KB2VuYWJsZWQYCiABKAgSGwoIcHJpb3JpdHkYCyABKA1CCbpIBioEGGQoACKvAQoKTmV3Sm9iSG9vaxInCgRuYW1lGAEgASgJQhm6SBZyFDISXlthLXowLTktXXszLDEwMH0kEhwKC2Rlc2NyaXB0aW9uGAIgASgJQge6SARyAhABEiwKBmNvbmZpZxgDIAEoCzIcLm1nbXQudjFhbHBoYTEuSm9iSG9va0NvbmZpZxIPCgdlbmFibGVkGAQgASgIEhsKCHByaW9yaXR5GAUgASgNQgm6SAYqBBhkKAAiiAMKDUpvYkhvb2tDb25maWcSNgoDc3FsGAUgASgLMicubWdtdC52MWFscGhhMS5Kb2JIb29rQ29uZmlnLkpvYlNxbEhvb2tIABqVAgoKSm9iU3FsSG9vaxIWCgVxdWVyeRgBIAEoCUIHukgEcgIQARIfCg1jb25uZWN0aW9uX2lkGAIgASgJQgi6SAVyA7ABARI+CgZ0aW1pbmcYAyABKAsyLi5tZ210LnYxYWxwaGExLkpvYkhvb2tDb25maWcuSm9iU3FsSG9vay5UaW1pbmcajQEKBlRpbWluZxI3CghwcmVfc3luYxgDIAEoCzIjLm1nbXQudjFhbHBoYTEuSm9iSG9va1RpbWluZ1ByZVN5bmNIABI5Cglwb3N0X3N5bmMYBCABKAsyJC5tZ210LnYxYWxwaGExLkpvYkhvb2tUaW1pbmdQb3N0U3luY0gAQg8KBnRpbWluZxIFukgCCAFCDwoGY29uZmlnEgW6SAIIAUoECAEQAkoECAIQA0oECAMQBEoECAQQBSIWChRKb2JIb29rVGltaW5nUHJlU3luYyIXChVKb2JIb29rVGltaW5nUG9zdFN5bmMiLgoSR2V0Sm9iSG9va3NSZXF1ZXN0EhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQEiPAoTR2V0Sm9iSG9va3NSZXNwb25zZRIlCgVob29rcxgBIAMoCzIWLm1nbXQudjFhbHBoYTEuSm9iSG9vayIpChFHZXRKb2JIb29rUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQEiOgoSR2V0Sm9iSG9va1Jlc3BvbnNlEiQKBGhvb2sYASABKAsyFi5tZ210LnYxYWxwaGExLkpvYkhvb2siTwoUQ3JlYXRlSm9iSG9va1JlcXVlc3QSDgoGam9iX2lkGAEgASgJEicKBGhvb2sYAiABKAsyGS5tZ210LnYxYWxwaGExLk5ld0pvYkhvb2siPQoVQ3JlYXRlSm9iSG9va1Jlc3BvbnNlEiQKBGhvb2sYASABKAsyFi5tZ210LnYxYWxwaGExLkpvYkhvb2siLAoURGVsZXRlSm9iSG9va1JlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIhcKFURlbGV0ZUpvYkhvb2tSZXNwb25zZSI9Ch1Jc0pvYkhvb2tOYW1lQXZhaWxhYmxlUmVxdWVzdBIOCgZqb2JfaWQYASABKAkSDAoEbmFtZRgCIAEoCSI2Ch5Jc0pvYkhvb2tOYW1lQXZhaWxhYmxlUmVzcG9uc2USFAoMaXNfYXZhaWxhYmxlGAEgASgIIs8BChRVcGRhdGVKb2JIb29rUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESJwoEbmFtZRgCIAEoCUIZukgWchQyEl5bYS16MC05LV17MywxMDB9JBIcCgtkZXNjcmlwdGlvbhgDIAEoCUIHukgEcgIQARIsCgZjb25maWcYBCABKAsyHC5tZ210LnYxYWxwaGExLkpvYkhvb2tDb25maWcSDwoHZW5hYmxlZBgFIAEoCBIbCghwcmlvcml0eRgGIAEoDUIJukgGKgQYZCgAIj0KFVVwZGF0ZUpvYkhvb2tSZXNwb25zZRIkCgRob29rGAEgASgLMhYubWdtdC52MWFscGhhMS5Kb2JIb29rIkEKGFNldEpvYkhvb2tFbmFibGVkUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESDwoHZW5hYmxlZBgCIAEoCCJBChlTZXRKb2JIb29rRW5hYmxlZFJlc3BvbnNlEiQKBGhvb2sYASABKAsyFi5tZ210LnYxYWxwaGExLkpvYkhvb2sizwEKIEdldEFjdGl2ZUpvYkhvb2tzQnlUaW1pbmdSZXF1ZXN0EhgKBmpvYl9pZBgBIAEoCUIIukgFcgOwAQESRgoGdGltaW5nGAIgASgOMjYubWdtdC52MWFscGhhMS5HZXRBY3RpdmVKb2JIb29rc0J5VGltaW5nUmVxdWVzdC5UaW1pbmciSQoGVGltaW5nEhYKElRJTUlOR19VTlNQRUNJRklFRBAAEhIKDlRJTUlOR19QUkVTWU5DEAESEwoPVElNSU5HX1BPU1RTWU5DEAIiSgohR2V0QWN0aXZlSm9iSG9va3NCeVRpbWluZ1Jlc3BvbnNlEiUKBWhvb2tzGAEgAygLMhYubWdtdC52MWFscGhhMS5Kb2JIb29rKm8KCUpvYlN0YXR1cxIaChZKT0JfU1RBVFVTX1VOU1BFQ0lGSUVEEAASFgoSSk9CX1NUQVRVU19FTkFCTEVEEAESFQoRSk9CX1NUQVRVU19QQVVTRUQQAxIXChNKT0JfU1RBVFVTX0RJU0FCTEVEEAQqpwEKDkFjdGl2aXR5U3RhdHVzEh8KG0FDVElWSVRZX1NUQVRVU19VTlNQRUNJRklFRBAAEh0KGUFDVElWSVRZX1NUQVRVU19TQ0hFRFVMRUQQARIbChdBQ1RJVklUWV9TVEFUVVNfU1RBUlRFRBACEhwKGEFDVElWSVRZX1NUQVRVU19DQU5DRUxFRBADEhoKFkFDVElWSVRZX1NUQVRVU19GQUlMRUQQBCqSAgoMSm9iUnVuU3RhdHVzEh4KGkpPQl9SVU5fU1RBVFVTX1VOU1BFQ0lGSUVEEAASGgoWSk9CX1JVTl9TVEFUVVNfUEVORElORxABEhoKFkpPQl9SVU5fU1RBVFVTX1JVTk5JTkcQAhIbChdKT0JfUlVOX1NUQVRVU19DT01QTEVURRADEhgKFEpPQl9SVU5fU1RBVFVTX0VSUk9SEAQSGwoXSk9CX1JVTl9TVEFUVVNfQ0FOQ0VMRUQQBRIdChlKT0JfUlVOX1NUQVRVU19URVJNSU5BVEVEEAYSGQoVSk9CX1JVTl9TVEFUVVNfRkFJTEVEEAcSHAoYSk9CX1JVTl9TVEFUVVNfVElNRURfT1VUEAgqfAoJTG9nV2luZG93EiIKHkxPR19XSU5ET1dfTk9fVElNRV9VTlNQRUNJRklFRBAAEhoKFkxPR19XSU5ET1dfRklGVEVFTl9NSU4QARIXChNMT0dfV0lORE9XX09ORV9IT1VSEAISFgoSTE9HX1dJTkRPV19PTkVfREFZEAMqdwoITG9nTGV2ZWwSGQoVTE9HX0xFVkVMX1VOU1BFQ0lGSUVEEAASEwoPTE9HX0xFVkVMX0RFQlVHEAESEgoOTE9HX0xFVkVMX0lORk8QAhISCg5MT0dfTEVWRUxfV0FSThADEhMKD0xPR19MRVZFTF9FUlJPUhAEMtYfCgpKb2JTZXJ2aWNlEk0KB0dldEpvYnMSHS5tZ210LnYxYWxwaGExLkdldEpvYnNSZXF1ZXN0Gh4ubWdtdC52MWFscGhhMS5HZXRKb2JzUmVzcG9uc2UiA5ACARJKCgZHZXRKb2ISHC5tZ210LnYxYWxwaGExLkdldEpvYlJlcXVlc3QaHS5tZ210LnYxYWxwaGExLkdldEpvYlJlc3BvbnNlIgOQAgESUAoJQ3JlYXRlSm9iEh8ubWdtdC52MWFscGhhMS5DcmVhdGVKb2JSZXF1ZXN0GiAubWdtdC52MWFscGhhMS5DcmVhdGVKb2JSZXNwb25zZSIAElAKCURlbGV0ZUpvYhIfLm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iUmVxdWVzdBogLm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iUmVzcG9uc2UiABJuChJJc0pvYk5hbWVBdmFpbGFibGUSKC5tZ210LnYxYWxwaGExLklzSm9iTmFtZUF2YWlsYWJsZVJlcXVlc3QaKS5tZ210LnYxYWxwaGExLklzSm9iTmFtZUF2YWlsYWJsZVJlc3BvbnNlIgOQAgESaAoRVXBkYXRlSm9iU2NoZWR1bGUSJy5tZ210LnYxYWxwaGExLlVwZGF0ZUpvYlNjaGVkdWxlUmVxdWVzdBooLm1nbXQudjFhbHBoYTEuVXBkYXRlSm9iU2NoZWR1bGVSZXNwb25zZSIAEoABChlVcGRhdGVKb2JTb3VyY2VDb25uZWN0aW9uEi8ubWdtdC52MWFscGhhMS5VcGRhdGVKb2JTb3VyY2VDb25uZWN0aW9uUmVxdWVzdBowLm1nbXQudjFhbHBoYTEuVXBkYXRlSm9iU291cmNlQ29ubmVjdGlvblJlc3BvbnNlIgASlQEKIFNldEpvYlNvdXJjZVNxbENvbm5lY3Rpb25TdWJzZXRzEjYubWdtdC52MWFscGhhMS5TZXRKb2JTb3VyY2VTcWxDb25uZWN0aW9uU3Vic2V0c1JlcXVlc3QaNy5tZ210LnYxYWxwaGExLlNldEpvYlNvdXJjZVNxbENvbm5lY3Rpb25TdWJzZXRzUmVzcG9uc2UiABKPAQoeVXBkYXRlSm9iRGVzdGluYXRpb25Db25uZWN0aW9uEjQubWdtdC52MWFscGhhMS5VcGRhdGVKb2JEZXN0aW5hdGlvbkNvbm5lY3Rpb25SZXF1ZXN0GjUubWdtdC52MWFscGhhMS5VcGRhdGVKb2JEZXN0aW5hdGlvbkNvbm5lY3Rpb25SZXNwb25zZSIAEo8BCh5EZWxldGVKb2JEZXN0aW5hdGlvbkNvbm5lY3Rpb24SNC5tZ210LnYxYWxwaGExLkRlbGV0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvblJlcXVlc3QaNS5tZ210LnYxYWxwaGExLkRlbGV0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvblJlc3BvbnNlIgASkgEKH0NyZWF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvbnMSNS5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYkRlc3RpbmF0aW9uQ29ubmVjdGlvbnNSZXF1ZXN0GjYubWdtdC52MWFscGhhMS5DcmVhdGVKb2JEZXN0aW5hdGlvbkNvbm5lY3Rpb25zUmVzcG9uc2UiABJNCghQYXVzZUpvYhIeLm1nbXQudjFhbHBoYTEuUGF1c2VKb2JSZXF1ZXN0Gh8ubWdtdC52MWFscGhhMS5QYXVzZUpvYlJlc3BvbnNlIgASaAoQR2V0Sm9iUmVjZW50UnVucxImLm1nbXQudjFhbHBoYTEuR2V0Sm9iUmVjZW50UnVuc1JlcXVlc3QaJy5tZ210LnYxYWxwaGExLkdldEpvYlJlY2VudFJ1bnNSZXNwb25zZSIDkAIBEmIKDkdldEpvYk5leHRSdW5zEiQubWdtdC52MWFscGhhMS5HZXRKb2JOZXh0UnVuc1JlcXVlc3QaJS5tZ210LnYxYWxwaGExLkdldEpvYk5leHRSdW5zUmVzcG9uc2UiA5ACARJcCgxHZXRKb2JTdGF0dXMSIi5tZ210LnYxYWxwaGExLkdldEpvYlN0YXR1c1JlcXVlc3QaIy5tZ210LnYxYWxwaGExLkdldEpvYlN0YXR1c1Jlc3BvbnNlIgOQAgESYgoOR2V0Sm9iU3RhdHVzZXMSJC5tZ210LnYxYWxwaGExLkdldEpvYlN0YXR1c2VzUmVxdWVzdBolLm1nbXQudjFhbHBoYTEuR2V0Sm9iU3RhdHVzZXNSZXNwb25zZSIDkAIBElYKCkdldEpvYlJ1bnMSIC5tZ210LnYxYWxwaGExLkdldEpvYlJ1bnNSZXF1ZXN0GiEubWdtdC52MWFscGhhMS5HZXRKb2JSdW5zUmVzcG9uc2UiA5ACARJlCg9HZXRKb2JSdW5FdmVudHMSJS5tZ210LnYxYWxwaGExLkdldEpvYlJ1bkV2ZW50c1JlcXVlc3QaJi5tZ210LnYxYWxwaGExLkdldEpvYlJ1bkV2ZW50c1Jlc3BvbnNlIgOQAgESUwoJR2V0Sm9iUnVuEh8ubWdtdC52MWFscGhhMS5HZXRKb2JSdW5SZXF1ZXN0GiAubWdtdC52MWFscGhhMS5HZXRKb2JSdW5SZXNwb25zZSIDkAIBElkKDERlbGV0ZUpvYlJ1bhIiLm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iUnVuUmVxdWVzdBojLm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iUnVuUmVzcG9uc2UiABJZCgxDcmVhdGVKb2JSdW4SIi5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYlJ1blJlcXVlc3QaIy5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYlJ1blJlc3BvbnNlIgASWQoMQ2FuY2VsSm9iUnVuEiIubWdtdC52MWFscGhhMS5DYW5jZWxKb2JSdW5SZXF1ZXN0GiMubWdtdC52MWFscGhhMS5DYW5jZWxKb2JSdW5SZXNwb25zZSIAEmIKD1Rlcm1pbmF0ZUpvYlJ1bhIlLm1nbXQudjFhbHBoYTEuVGVybWluYXRlSm9iUnVuUmVxdWVzdBomLm1nbXQudjFhbHBoYTEuVGVybWluYXRlSm9iUnVuUmVzcG9uc2UiABJwChNHZXRKb2JSdW5Mb2dzU3RyZWFtEikubWdtdC52MWFscGhhMS5HZXRKb2JSdW5Mb2dzU3RyZWFtUmVxdWVzdBoqLm1nbXQudjFhbHBoYTEuR2V0Sm9iUnVuTG9nc1N0cmVhbVJlc3BvbnNlIgAwARJcCg1HZXRKb2JSdW5Mb2dzEiMubWdtdC52MWFscGhhMS5HZXRKb2JSdW5Mb2dzUmVxdWVzdBokLm1nbXQudjFhbHBoYTEuR2V0Sm9iUnVuTG9nc1Jlc3BvbnNlIgASdAoVU2V0Sm9iV29ya2Zsb3dPcHRpb25zEisubWdtdC52MWFscGhhMS5TZXRKb2JXb3JrZmxvd09wdGlvbnNSZXF1ZXN0GiwubWdtdC52MWFscGhhMS5TZXRKb2JXb3JrZmxvd09wdGlvbnNSZXNwb25zZSIAEmgKEVNldEpvYlN5bmNPcHRpb25zEicubWdtdC52MWFscGhhMS5TZXRKb2JTeW5jT3B0aW9uc1JlcXVlc3QaKC5tZ210LnYxYWxwaGExLlNldEpvYlN5bmNPcHRpb25zUmVzcG9uc2UiABJuChNWYWxpZGF0ZUpvYk1hcHBpbmdzEikubWdtdC52MWFscGhhMS5WYWxpZGF0ZUpvYk1hcHBpbmdzUmVxdWVzdBoqLm1nbXQudjFhbHBoYTEuVmFsaWRhdGVKb2JNYXBwaW5nc1Jlc3BvbnNlIgASXAoNR2V0UnVuQ29udGV4dBIjLm1nbXQudjFhbHBoYTEuR2V0UnVuQ29udGV4dFJlcXVlc3QaJC5tZ210LnYxYWxwaGExLkdldFJ1bkNvbnRleHRSZXNwb25zZSIAElwKDVNldFJ1bkNvbnRleHQSIy5tZ210LnYxYWxwaGExLlNldFJ1bkNvbnRleHRSZXF1ZXN0GiQubWdtdC52MWFscGhhMS5TZXRSdW5Db250ZXh0UmVzcG9uc2UiABJhCg5TZXRSdW5Db250ZXh0cxIkLm1nbXQudjFhbHBoYTEuU2V0UnVuQ29udGV4dHNSZXF1ZXN0GiUubWdtdC52MWFscGhhMS5TZXRSdW5Db250ZXh0c1Jlc3BvbnNlIgAoARJZCgtHZXRKb2JIb29rcxIhLm1nbXQudjFhbHBoYTEuR2V0Sm9iSG9va3NSZXF1ZXN0GiIubWdtdC52MWFscGhhMS5HZXRKb2JIb29rc1Jlc3BvbnNlIgOQAgESVgoKR2V0Sm9iSG9vaxIgLm1nbXQudjFhbHBoYTEuR2V0Sm9iSG9va1JlcXVlc3QaIS5tZ210LnYxYWxwaGExLkdldEpvYkhvb2tSZXNwb25zZSIDkAIBElwKDUNyZWF0ZUpvYkhvb2sSIy5tZ210LnYxYWxwaGExLkNyZWF0ZUpvYkhvb2tSZXF1ZXN0GiQubWdtdC52MWFscGhhMS5DcmVhdGVKb2JIb29rUmVzcG9uc2UiABJcCg1EZWxldGVKb2JIb29rEiMubWdtdC52MWFscGhhMS5EZWxldGVKb2JIb29rUmVxdWVzdBokLm1nbXQudjFhbHBoYTEuRGVsZXRlSm9iSG9va1Jlc3BvbnNlIgASdwoWSXNKb2JIb29rTmFtZUF2YWlsYWJsZRIsLm1nbXQudjFhbHBoYTEuSXNKb2JIb29rTmFtZUF2YWlsYWJsZVJlcXVlc3QaLS5tZ210LnYxYWxwaGExLklzSm9iSG9va05hbWVBdmFpbGFibGVSZXNwb25zZSIAElwKDVVwZGF0ZUpvYkhvb2sSIy5tZ210LnYxYWxwaGExLlVwZGF0ZUpvYkhvb2tSZXF1ZXN0GiQubWdtdC52MWFscGhhMS5VcGRhdGVKb2JIb29rUmVzcG9uc2UiABJoChFTZXRKb2JIb29rRW5hYmxlZBInLm1nbXQudjFhbHBoYTEuU2V0Sm9iSG9va0VuYWJsZWRSZXF1ZXN0GigubWdtdC52MWFscGhhMS5TZXRKb2JIb29rRW5hYmxlZFJlc3BvbnNlIgASgwEKGUdldEFjdGl2ZUpvYkhvb2tzQnlUaW1pbmcSLy5tZ210LnYxYWxwaGExLkdldEFjdGl2ZUpvYkhvb2tzQnlUaW1pbmdSZXF1ZXN0GjAubWdtdC52MWFscGhhMS5HZXRBY3RpdmVKb2JIb29rc0J5VGltaW5nUmVzcG9uc2UiA5ACAULEAQoRY29tLm1nbXQudjFhbHBoYTFCCEpvYlByb3RvUAFaUGdpdGh1Yi5jb20vbnVjbGV1c2Nsb3VkL25lb3N5bmMvYmFja2VuZC9nZW4vZ28vcHJvdG9zL21nbXQvdjFhbHBoYTE7bWdtdHYxYWxwaGExogIDTVhYqgINTWdtdC5WMWFscGhhMcoCDU1nbXRcVjFhbHBoYTHiAhlNZ210XFYxYWxwaGExXEdQQk1ldGFkYXRh6gIOTWdtdDo6VjFhbHBoYTFiBnByb3RvMw", [file_buf_validate_validate, file_google_protobuf_timestamp, file_mgmt_v1alpha1_transformer]);
/**
* @generated from message mgmt.v1alpha1.GetJobsRequest
@@ -3557,6 +3557,98 @@ export type GetJobRunLogsStreamResponse = Message<"mgmt.v1alpha1.GetJobRunLogsSt
export const GetJobRunLogsStreamResponseSchema: GenMessage = /*@__PURE__*/
messageDesc(file_mgmt_v1alpha1_job, 109);
+/**
+ * @generated from message mgmt.v1alpha1.GetJobRunLogsRequest
+ */
+export type GetJobRunLogsRequest = Message<"mgmt.v1alpha1.GetJobRunLogsRequest"> & {
+ /**
+ * The unique identifier of the job run
+ *
+ * @generated from field: string job_run_id = 1;
+ */
+ jobRunId: string;
+
+ /**
+ * The unique identifier of the account
+ *
+ * @generated from field: string account_id = 2;
+ */
+ accountId: string;
+
+ /**
+ * The time window in which to retrieve the logs
+ *
+ * @generated from field: mgmt.v1alpha1.LogWindow window = 3;
+ */
+ window: LogWindow;
+
+ /**
+ * Optionally provide a max log limit
+ *
+ * @generated from field: optional int64 max_log_lines = 4;
+ */
+ maxLogLines?: bigint;
+
+ /**
+ * Provide a list of log levels to filter by. If any of these are UNSPECIFIED, all log levels are returned.
+ *
+ * @generated from field: repeated mgmt.v1alpha1.LogLevel log_levels = 5;
+ */
+ logLevels: LogLevel[];
+};
+
+/**
+ * Describes the message mgmt.v1alpha1.GetJobRunLogsRequest.
+ * Use `create(GetJobRunLogsRequestSchema)` to create a new message.
+ */
+export const GetJobRunLogsRequestSchema: GenMessage = /*@__PURE__*/
+ messageDesc(file_mgmt_v1alpha1_job, 110);
+
+/**
+ * @generated from message mgmt.v1alpha1.GetJobRunLogsResponse
+ */
+export type GetJobRunLogsResponse = Message<"mgmt.v1alpha1.GetJobRunLogsResponse"> & {
+ /**
+ * The list of log lines
+ *
+ * @generated from field: repeated mgmt.v1alpha1.GetJobRunLogsResponse.LogLine log_lines = 1;
+ */
+ logLines: GetJobRunLogsResponse_LogLine[];
+};
+
+/**
+ * Describes the message mgmt.v1alpha1.GetJobRunLogsResponse.
+ * Use `create(GetJobRunLogsResponseSchema)` to create a new message.
+ */
+export const GetJobRunLogsResponseSchema: GenMessage = /*@__PURE__*/
+ messageDesc(file_mgmt_v1alpha1_job, 111);
+
+/**
+ * @generated from message mgmt.v1alpha1.GetJobRunLogsResponse.LogLine
+ */
+export type GetJobRunLogsResponse_LogLine = Message<"mgmt.v1alpha1.GetJobRunLogsResponse.LogLine"> & {
+ /**
+ * The log line
+ *
+ * @generated from field: string log_line = 1;
+ */
+ logLine: string;
+
+ /**
+ * The timestamp of the log line
+ *
+ * @generated from field: optional google.protobuf.Timestamp timestamp = 2;
+ */
+ timestamp?: Timestamp;
+};
+
+/**
+ * Describes the message mgmt.v1alpha1.GetJobRunLogsResponse.LogLine.
+ * Use `create(GetJobRunLogsResponse_LogLineSchema)` to create a new message.
+ */
+export const GetJobRunLogsResponse_LogLineSchema: GenMessage = /*@__PURE__*/
+ messageDesc(file_mgmt_v1alpha1_job, 111, 0);
+
/**
* @generated from message mgmt.v1alpha1.SetJobWorkflowOptionsRequest
*/
@@ -3581,7 +3673,7 @@ export type SetJobWorkflowOptionsRequest = Message<"mgmt.v1alpha1.SetJobWorkflow
* Use `create(SetJobWorkflowOptionsRequestSchema)` to create a new message.
*/
export const SetJobWorkflowOptionsRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 110);
+ messageDesc(file_mgmt_v1alpha1_job, 112);
/**
* @generated from message mgmt.v1alpha1.SetJobWorkflowOptionsResponse
@@ -3600,7 +3692,7 @@ export type SetJobWorkflowOptionsResponse = Message<"mgmt.v1alpha1.SetJobWorkflo
* Use `create(SetJobWorkflowOptionsResponseSchema)` to create a new message.
*/
export const SetJobWorkflowOptionsResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 111);
+ messageDesc(file_mgmt_v1alpha1_job, 113);
/**
* @generated from message mgmt.v1alpha1.SetJobSyncOptionsRequest
@@ -3626,7 +3718,7 @@ export type SetJobSyncOptionsRequest = Message<"mgmt.v1alpha1.SetJobSyncOptionsR
* Use `create(SetJobSyncOptionsRequestSchema)` to create a new message.
*/
export const SetJobSyncOptionsRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 112);
+ messageDesc(file_mgmt_v1alpha1_job, 114);
/**
* @generated from message mgmt.v1alpha1.SetJobSyncOptionsResponse
@@ -3645,7 +3737,7 @@ export type SetJobSyncOptionsResponse = Message<"mgmt.v1alpha1.SetJobSyncOptions
* Use `create(SetJobSyncOptionsResponseSchema)` to create a new message.
*/
export const SetJobSyncOptionsResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 113);
+ messageDesc(file_mgmt_v1alpha1_job, 115);
/**
* @generated from message mgmt.v1alpha1.ValidateJobMappingsRequest
@@ -3692,7 +3784,7 @@ export type ValidateJobMappingsRequest = Message<"mgmt.v1alpha1.ValidateJobMappi
* Use `create(ValidateJobMappingsRequestSchema)` to create a new message.
*/
export const ValidateJobMappingsRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 114);
+ messageDesc(file_mgmt_v1alpha1_job, 116);
/**
* @generated from message mgmt.v1alpha1.ColumnError
@@ -3732,7 +3824,7 @@ export type ColumnError = Message<"mgmt.v1alpha1.ColumnError"> & {
* Use `create(ColumnErrorSchema)` to create a new message.
*/
export const ColumnErrorSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 115);
+ messageDesc(file_mgmt_v1alpha1_job, 117);
/**
* @generated from message mgmt.v1alpha1.ColumnWarning
@@ -3772,7 +3864,7 @@ export type ColumnWarning = Message<"mgmt.v1alpha1.ColumnWarning"> & {
* Use `create(ColumnWarningSchema)` to create a new message.
*/
export const ColumnWarningSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 116);
+ messageDesc(file_mgmt_v1alpha1_job, 118);
/**
* @generated from message mgmt.v1alpha1.DatabaseError
@@ -3791,7 +3883,7 @@ export type DatabaseError = Message<"mgmt.v1alpha1.DatabaseError"> & {
* Use `create(DatabaseErrorSchema)` to create a new message.
*/
export const DatabaseErrorSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 117);
+ messageDesc(file_mgmt_v1alpha1_job, 119);
/**
* @generated from message mgmt.v1alpha1.ValidateJobMappingsResponse
@@ -3824,7 +3916,7 @@ export type ValidateJobMappingsResponse = Message<"mgmt.v1alpha1.ValidateJobMapp
* Use `create(ValidateJobMappingsResponseSchema)` to create a new message.
*/
export const ValidateJobMappingsResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 118);
+ messageDesc(file_mgmt_v1alpha1_job, 120);
/**
* @generated from message mgmt.v1alpha1.VirtualForeignKey
@@ -3857,7 +3949,7 @@ export type VirtualForeignKey = Message<"mgmt.v1alpha1.VirtualForeignKey"> & {
* Use `create(VirtualForeignKeySchema)` to create a new message.
*/
export const VirtualForeignKeySchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 119);
+ messageDesc(file_mgmt_v1alpha1_job, 121);
/**
* @generated from message mgmt.v1alpha1.VirtualForeignConstraint
@@ -3897,7 +3989,7 @@ export type VirtualForeignConstraint = Message<"mgmt.v1alpha1.VirtualForeignCons
* Use `create(VirtualForeignConstraintSchema)` to create a new message.
*/
export const VirtualForeignConstraintSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 120);
+ messageDesc(file_mgmt_v1alpha1_job, 122);
/**
* @generated from message mgmt.v1alpha1.RunContextKey
@@ -3930,7 +4022,7 @@ export type RunContextKey = Message<"mgmt.v1alpha1.RunContextKey"> & {
* Use `create(RunContextKeySchema)` to create a new message.
*/
export const RunContextKeySchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 121);
+ messageDesc(file_mgmt_v1alpha1_job, 123);
/**
* @generated from message mgmt.v1alpha1.GetRunContextRequest
@@ -3949,7 +4041,7 @@ export type GetRunContextRequest = Message<"mgmt.v1alpha1.GetRunContextRequest">
* Use `create(GetRunContextRequestSchema)` to create a new message.
*/
export const GetRunContextRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 122);
+ messageDesc(file_mgmt_v1alpha1_job, 124);
/**
* @generated from message mgmt.v1alpha1.GetRunContextResponse
@@ -3968,7 +4060,7 @@ export type GetRunContextResponse = Message<"mgmt.v1alpha1.GetRunContextResponse
* Use `create(GetRunContextResponseSchema)` to create a new message.
*/
export const GetRunContextResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 123);
+ messageDesc(file_mgmt_v1alpha1_job, 125);
/**
* @generated from message mgmt.v1alpha1.SetRunContextRequest
@@ -3994,7 +4086,7 @@ export type SetRunContextRequest = Message<"mgmt.v1alpha1.SetRunContextRequest">
* Use `create(SetRunContextRequestSchema)` to create a new message.
*/
export const SetRunContextRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 124);
+ messageDesc(file_mgmt_v1alpha1_job, 126);
/**
* @generated from message mgmt.v1alpha1.SetRunContextResponse
@@ -4007,7 +4099,7 @@ export type SetRunContextResponse = Message<"mgmt.v1alpha1.SetRunContextResponse
* Use `create(SetRunContextResponseSchema)` to create a new message.
*/
export const SetRunContextResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 125);
+ messageDesc(file_mgmt_v1alpha1_job, 127);
/**
* @generated from message mgmt.v1alpha1.SetRunContextsRequest
@@ -4033,7 +4125,7 @@ export type SetRunContextsRequest = Message<"mgmt.v1alpha1.SetRunContextsRequest
* Use `create(SetRunContextsRequestSchema)` to create a new message.
*/
export const SetRunContextsRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 126);
+ messageDesc(file_mgmt_v1alpha1_job, 128);
/**
* @generated from message mgmt.v1alpha1.SetRunContextsResponse
@@ -4046,7 +4138,7 @@ export type SetRunContextsResponse = Message<"mgmt.v1alpha1.SetRunContextsRespon
* Use `create(SetRunContextsResponseSchema)` to create a new message.
*/
export const SetRunContextsResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 127);
+ messageDesc(file_mgmt_v1alpha1_job, 129);
/**
* @generated from message mgmt.v1alpha1.JobHook
@@ -4136,7 +4228,7 @@ export type JobHook = Message<"mgmt.v1alpha1.JobHook"> & {
* Use `create(JobHookSchema)` to create a new message.
*/
export const JobHookSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 128);
+ messageDesc(file_mgmt_v1alpha1_job, 130);
/**
* @generated from message mgmt.v1alpha1.NewJobHook
@@ -4184,7 +4276,7 @@ export type NewJobHook = Message<"mgmt.v1alpha1.NewJobHook"> & {
* Use `create(NewJobHookSchema)` to create a new message.
*/
export const NewJobHookSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 129);
+ messageDesc(file_mgmt_v1alpha1_job, 131);
/**
* Contains the specific hook type configurations.
@@ -4211,7 +4303,7 @@ export type JobHookConfig = Message<"mgmt.v1alpha1.JobHookConfig"> & {
* Use `create(JobHookConfigSchema)` to create a new message.
*/
export const JobHookConfigSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 130);
+ messageDesc(file_mgmt_v1alpha1_job, 132);
/**
* Configuration for SQL-based hooks
@@ -4246,7 +4338,7 @@ export type JobHookConfig_JobSqlHook = Message<"mgmt.v1alpha1.JobHookConfig.JobS
* Use `create(JobHookConfig_JobSqlHookSchema)` to create a new message.
*/
export const JobHookConfig_JobSqlHookSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 130, 0);
+ messageDesc(file_mgmt_v1alpha1_job, 132, 0);
/**
* @generated from message mgmt.v1alpha1.JobHookConfig.JobSqlHook.Timing
@@ -4282,7 +4374,7 @@ export type JobHookConfig_JobSqlHook_Timing = Message<"mgmt.v1alpha1.JobHookConf
* Use `create(JobHookConfig_JobSqlHook_TimingSchema)` to create a new message.
*/
export const JobHookConfig_JobSqlHook_TimingSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 130, 0, 0);
+ messageDesc(file_mgmt_v1alpha1_job, 132, 0, 0);
/**
* Configures the job hook to run before the first table sync.
@@ -4299,7 +4391,7 @@ export type JobHookTimingPreSync = Message<"mgmt.v1alpha1.JobHookTimingPreSync">
* Use `create(JobHookTimingPreSyncSchema)` to create a new message.
*/
export const JobHookTimingPreSyncSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 131);
+ messageDesc(file_mgmt_v1alpha1_job, 133);
/**
* Configures the job hook to run after the last table sync.
@@ -4314,7 +4406,7 @@ export type JobHookTimingPostSync = Message<"mgmt.v1alpha1.JobHookTimingPostSync
* Use `create(JobHookTimingPostSyncSchema)` to create a new message.
*/
export const JobHookTimingPostSyncSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 132);
+ messageDesc(file_mgmt_v1alpha1_job, 134);
/**
* @generated from message mgmt.v1alpha1.GetJobHooksRequest
@@ -4333,7 +4425,7 @@ export type GetJobHooksRequest = Message<"mgmt.v1alpha1.GetJobHooksRequest"> & {
* Use `create(GetJobHooksRequestSchema)` to create a new message.
*/
export const GetJobHooksRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 133);
+ messageDesc(file_mgmt_v1alpha1_job, 135);
/**
* @generated from message mgmt.v1alpha1.GetJobHooksResponse
@@ -4352,7 +4444,7 @@ export type GetJobHooksResponse = Message<"mgmt.v1alpha1.GetJobHooksResponse"> &
* Use `create(GetJobHooksResponseSchema)` to create a new message.
*/
export const GetJobHooksResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 134);
+ messageDesc(file_mgmt_v1alpha1_job, 136);
/**
* @generated from message mgmt.v1alpha1.GetJobHookRequest
@@ -4371,7 +4463,7 @@ export type GetJobHookRequest = Message<"mgmt.v1alpha1.GetJobHookRequest"> & {
* Use `create(GetJobHookRequestSchema)` to create a new message.
*/
export const GetJobHookRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 135);
+ messageDesc(file_mgmt_v1alpha1_job, 137);
/**
* @generated from message mgmt.v1alpha1.GetJobHookResponse
@@ -4390,7 +4482,7 @@ export type GetJobHookResponse = Message<"mgmt.v1alpha1.GetJobHookResponse"> & {
* Use `create(GetJobHookResponseSchema)` to create a new message.
*/
export const GetJobHookResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 136);
+ messageDesc(file_mgmt_v1alpha1_job, 138);
/**
* @generated from message mgmt.v1alpha1.CreateJobHookRequest
@@ -4416,7 +4508,7 @@ export type CreateJobHookRequest = Message<"mgmt.v1alpha1.CreateJobHookRequest">
* Use `create(CreateJobHookRequestSchema)` to create a new message.
*/
export const CreateJobHookRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 137);
+ messageDesc(file_mgmt_v1alpha1_job, 139);
/**
* @generated from message mgmt.v1alpha1.CreateJobHookResponse
@@ -4435,7 +4527,7 @@ export type CreateJobHookResponse = Message<"mgmt.v1alpha1.CreateJobHookResponse
* Use `create(CreateJobHookResponseSchema)` to create a new message.
*/
export const CreateJobHookResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 138);
+ messageDesc(file_mgmt_v1alpha1_job, 140);
/**
* @generated from message mgmt.v1alpha1.DeleteJobHookRequest
@@ -4454,7 +4546,7 @@ export type DeleteJobHookRequest = Message<"mgmt.v1alpha1.DeleteJobHookRequest">
* Use `create(DeleteJobHookRequestSchema)` to create a new message.
*/
export const DeleteJobHookRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 139);
+ messageDesc(file_mgmt_v1alpha1_job, 141);
/**
* @generated from message mgmt.v1alpha1.DeleteJobHookResponse
@@ -4467,7 +4559,7 @@ export type DeleteJobHookResponse = Message<"mgmt.v1alpha1.DeleteJobHookResponse
* Use `create(DeleteJobHookResponseSchema)` to create a new message.
*/
export const DeleteJobHookResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 140);
+ messageDesc(file_mgmt_v1alpha1_job, 142);
/**
* @generated from message mgmt.v1alpha1.IsJobHookNameAvailableRequest
@@ -4493,7 +4585,7 @@ export type IsJobHookNameAvailableRequest = Message<"mgmt.v1alpha1.IsJobHookName
* Use `create(IsJobHookNameAvailableRequestSchema)` to create a new message.
*/
export const IsJobHookNameAvailableRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 141);
+ messageDesc(file_mgmt_v1alpha1_job, 143);
/**
* @generated from message mgmt.v1alpha1.IsJobHookNameAvailableResponse
@@ -4512,7 +4604,7 @@ export type IsJobHookNameAvailableResponse = Message<"mgmt.v1alpha1.IsJobHookNam
* Use `create(IsJobHookNameAvailableResponseSchema)` to create a new message.
*/
export const IsJobHookNameAvailableResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 142);
+ messageDesc(file_mgmt_v1alpha1_job, 144);
/**
* @generated from message mgmt.v1alpha1.UpdateJobHookRequest
@@ -4567,7 +4659,7 @@ export type UpdateJobHookRequest = Message<"mgmt.v1alpha1.UpdateJobHookRequest">
* Use `create(UpdateJobHookRequestSchema)` to create a new message.
*/
export const UpdateJobHookRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 143);
+ messageDesc(file_mgmt_v1alpha1_job, 145);
/**
* @generated from message mgmt.v1alpha1.UpdateJobHookResponse
@@ -4586,7 +4678,7 @@ export type UpdateJobHookResponse = Message<"mgmt.v1alpha1.UpdateJobHookResponse
* Use `create(UpdateJobHookResponseSchema)` to create a new message.
*/
export const UpdateJobHookResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 144);
+ messageDesc(file_mgmt_v1alpha1_job, 146);
/**
* @generated from message mgmt.v1alpha1.SetJobHookEnabledRequest
@@ -4612,7 +4704,7 @@ export type SetJobHookEnabledRequest = Message<"mgmt.v1alpha1.SetJobHookEnabledR
* Use `create(SetJobHookEnabledRequestSchema)` to create a new message.
*/
export const SetJobHookEnabledRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 145);
+ messageDesc(file_mgmt_v1alpha1_job, 147);
/**
* @generated from message mgmt.v1alpha1.SetJobHookEnabledResponse
@@ -4631,7 +4723,7 @@ export type SetJobHookEnabledResponse = Message<"mgmt.v1alpha1.SetJobHookEnabled
* Use `create(SetJobHookEnabledResponseSchema)` to create a new message.
*/
export const SetJobHookEnabledResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 146);
+ messageDesc(file_mgmt_v1alpha1_job, 148);
/**
* @generated from message mgmt.v1alpha1.GetActiveJobHooksByTimingRequest
@@ -4657,7 +4749,7 @@ export type GetActiveJobHooksByTimingRequest = Message<"mgmt.v1alpha1.GetActiveJ
* Use `create(GetActiveJobHooksByTimingRequestSchema)` to create a new message.
*/
export const GetActiveJobHooksByTimingRequestSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 147);
+ messageDesc(file_mgmt_v1alpha1_job, 149);
/**
* @generated from enum mgmt.v1alpha1.GetActiveJobHooksByTimingRequest.Timing
@@ -4689,7 +4781,7 @@ export enum GetActiveJobHooksByTimingRequest_Timing {
* Describes the enum mgmt.v1alpha1.GetActiveJobHooksByTimingRequest.Timing.
*/
export const GetActiveJobHooksByTimingRequest_TimingSchema: GenEnum = /*@__PURE__*/
- enumDesc(file_mgmt_v1alpha1_job, 147, 0);
+ enumDesc(file_mgmt_v1alpha1_job, 149, 0);
/**
* @generated from message mgmt.v1alpha1.GetActiveJobHooksByTimingResponse
@@ -4708,7 +4800,7 @@ export type GetActiveJobHooksByTimingResponse = Message<"mgmt.v1alpha1.GetActive
* Use `create(GetActiveJobHooksByTimingResponseSchema)` to create a new message.
*/
export const GetActiveJobHooksByTimingResponseSchema: GenMessage = /*@__PURE__*/
- messageDesc(file_mgmt_v1alpha1_job, 148);
+ messageDesc(file_mgmt_v1alpha1_job, 150);
/**
* @generated from enum mgmt.v1alpha1.JobStatus
@@ -5166,6 +5258,17 @@ export const JobService: GenService<{
input: typeof GetJobRunLogsStreamRequestSchema;
output: typeof GetJobRunLogsStreamResponseSchema;
},
+ /**
+ * Returns a list of logs from the worker nodes that pertain to a specific job run.
+ * Equivalent to the stream endpoint, but runs in a unary fashion.
+ *
+ * @generated from rpc mgmt.v1alpha1.JobService.GetJobRunLogs
+ */
+ getJobRunLogs: {
+ methodKind: "unary";
+ input: typeof GetJobRunLogsRequestSchema;
+ output: typeof GetJobRunLogsResponseSchema;
+ },
/**
* Set any job workflow options. Must provide entire object as is it will fully override the previous configuration
*
diff --git a/go.mod b/go.mod
index e917ce376e..905d4210a2 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
cloud.google.com/go/storage v1.50.0
connectrpc.com/connect v1.18.1
connectrpc.com/grpchealth v1.3.0
- connectrpc.com/grpcreflect v1.2.0
+ connectrpc.com/grpcreflect v1.3.0
connectrpc.com/otelconnect v0.7.1
github.com/Azure/azure-sdk-for-go/sdk/ai/azopenai v0.7.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0
@@ -20,12 +20,12 @@ require (
github.com/auth0/go-auth0 v1.14.0
github.com/auth0/go-jwt-middleware/v2 v2.2.2
github.com/aws/aws-sdk-go-v2 v1.33.0
- github.com/aws/aws-sdk-go-v2/config v1.29.0
- github.com/aws/aws-sdk-go-v2/credentials v1.17.53
- github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.4
- github.com/aws/aws-sdk-go-v2/service/s3 v1.73.1
- github.com/aws/aws-sdk-go-v2/service/sts v1.33.8
- github.com/aws/smithy-go v1.22.1
+ github.com/aws/aws-sdk-go-v2/config v1.29.1
+ github.com/aws/aws-sdk-go-v2/credentials v1.17.54
+ github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.5
+ github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2
+ github.com/aws/aws-sdk-go-v2/service/sts v1.33.9
+ github.com/aws/smithy-go v1.22.2
github.com/bufbuild/protovalidate-go v0.8.2
github.com/casbin/casbin/v2 v2.103.0
github.com/cenkalti/backoff/v4 v4.3.0
@@ -83,14 +83,14 @@ require (
go.opentelemetry.io/otel/sdk v1.34.0
go.opentelemetry.io/otel/sdk/metric v1.34.0
go.opentelemetry.io/otel/trace v1.34.0
- go.temporal.io/api v1.43.1
+ go.temporal.io/api v1.43.2
go.temporal.io/sdk v1.32.1
go.temporal.io/sdk/contrib/opentelemetry v0.6.0
golang.org/x/crypto v0.32.0
golang.org/x/net v0.34.0
golang.org/x/sync v0.10.0
golang.org/x/term v0.28.0
- google.golang.org/api v0.217.0
+ google.golang.org/api v0.218.0
google.golang.org/grpc v1.69.4
google.golang.org/protobuf v1.36.3
gopkg.in/yaml.v2 v2.4.0
@@ -167,7 +167,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.18.7 // indirect
github.com/aws/aws-sdk-go-v2/service/firehose v1.24.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9 // indirect
@@ -175,8 +175,8 @@ require (
github.com/aws/aws-sdk-go-v2/service/lambda v1.50.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sns v1.27.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.7 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.24.10 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/benhoyt/goawk v1.25.0 // indirect
diff --git a/go.sum b/go.sum
index 5a3db85177..80f3cb4d72 100644
--- a/go.sum
+++ b/go.sum
@@ -644,8 +644,8 @@ connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
connectrpc.com/grpchealth v1.3.0 h1:FA3OIwAvuMokQIXQrY5LbIy8IenftksTP/lG4PbYN+E=
connectrpc.com/grpchealth v1.3.0/go.mod h1:3vpqmX25/ir0gVgW6RdnCPPZRcR6HvqtXX5RNPmDXHM=
-connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U=
-connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY=
+connectrpc.com/grpcreflect v1.3.0 h1:Y4V+ACf8/vOb1XOc251Qun7jMB75gCUNw6llvB9csXc=
+connectrpc.com/grpcreflect v1.3.0/go.mod h1:nfloOtCS8VUQOQ1+GTdFzVg2CJo4ZGaat8JIovCtDYs=
connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY=
connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms=
contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
@@ -865,12 +865,12 @@ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwU
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc=
github.com/aws/aws-sdk-go-v2/config v1.15.3/go.mod h1:9YL3v07Xc/ohTsxFXzan9ZpFpdTOFl4X65BAKYaz8jg=
github.com/aws/aws-sdk-go-v2/config v1.25.3/go.mod h1:tAByZy03nH5jcq0vZmkcVoo6tRzRHEwSFx3QW4NmDw8=
-github.com/aws/aws-sdk-go-v2/config v1.29.0 h1:Vk/u4jof33or1qAQLdofpjKV7mQQT7DcUpnYx8kdmxY=
-github.com/aws/aws-sdk-go-v2/config v1.29.0/go.mod h1:iXAZK3Gxvpq3tA+B9WaDYpZis7M8KFgdrDPMmHrgbJM=
+github.com/aws/aws-sdk-go-v2/config v1.29.1 h1:JZhGawAyZ/EuJeBtbQYnaoftczcb2drR2Iq36Wgz4sQ=
+github.com/aws/aws-sdk-go-v2/config v1.29.1/go.mod h1:7bR2YD5euaxBhzt2y/oDkt3uNRb6tjFp98GlTFueRwk=
github.com/aws/aws-sdk-go-v2/credentials v1.11.2/go.mod h1:j8YsY9TXTm31k4eFhspiQicfXPLZ0gYXA50i4gxPE8g=
github.com/aws/aws-sdk-go-v2/credentials v1.16.2/go.mod h1:sDdvGhXrSVT5yzBDR7qXz+rhbpiMpUYfF3vJ01QSdrc=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.53 h1:lwrVhiEDW5yXsuVKlFVUnR2R50zt2DklhOyeLETqDuE=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.53/go.mod h1:CkqM1bIw/xjEpBMhBnvqUXYZbpCFuj6dnCAyDk2AtAY=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.54 h1:4UmqeOqJPvdvASZWrKlhzpRahAulBfyTJQUaYy4+hEI=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.54/go.mod h1:RTdfo0P0hbbTxIhmQrOsC/PquBZGabEPnCaxxKRPSnI=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.12.17 h1:jPuObStSZU1cGheSslAbF2nA4c/IgeIQA1X9frB60Oc=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.12.17/go.mod h1:df3uvEupLM3MkLim3BDkCaRpgAROW7wk41dwNQjw0kA=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression v1.6.17 h1:XJDx0IEeuLpyWUBdhRhoACpgYHGiQTerXSx6YEWKmgs=
@@ -900,8 +900,8 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28 h1:7kpeALOUeThs2kEjlAxlADAVfxK
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28/go.mod h1:pyaOYEdp1MJWgtXLy6q80r3DhsVdOIOZNB9hdTcJIvI=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.2 h1:vQfCIHSDouEvbE4EuDrlCGKcrtABEqF3cMt61nGEV4g=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.2/go.mod h1:3ToKMEhVj+Q+HzZ8Hqin6LdAKtsi3zVXVNUPpQMd+Xk=
-github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.4 h1:pK2f6BM2vfbWOvjirUIabQH52fa1MycnFi1F8Ismeog=
-github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.4/go.mod h1:2xlKGs8OTgN92fRVfP4EgFgQGhYwVI7LQ2PLQ0tIFAQ=
+github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.5 h1:RLbuYls/4gmY3AIHVyCLZgRjclRlSbUEUXLeva6C81Y=
+github.com/aws/aws-sdk-go-v2/service/dynamodb v1.39.5/go.mod h1:2xlKGs8OTgN92fRVfP4EgFgQGhYwVI7LQ2PLQ0tIFAQ=
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.18.7 h1:srShyROqxzC7p18Ws8mqM2sqxJO/8L3Kpiqf+NboJLg=
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.18.7/go.mod h1:9efZgg4nJCGRp91MuHhkwd2kvyp7PWLRYYk5WjEQ5ts=
github.com/aws/aws-sdk-go-v2/service/firehose v1.24.0 h1:U3F5oeq3Lp1jv9ebLHNr1OSBjCP7qwIOuj+tNqJOuzw=
@@ -912,8 +912,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhv
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3/go.mod h1:Seb8KNmD6kVTjwRjVEgOT5hPin6sq+v4C2ycJQDwuH8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.3/go.mod h1:R+/S1O4TYpcktbVwddeOYg+uwUfLhADP2S/x4QwsCTM=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.1 h1:mJ9FRktB8v1Ihpqwfk0AWvYEd0FgQtLsshc2Qb2TVc8=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.1/go.mod h1:dIW8puxSbYLSPv/ju0d9A3CpwXdtqvJtYKDMVmPLOWE=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2 h1:e6um6+DWYQP1XCa+E9YVtG/9v1qk5lyAOelMOVwSyO8=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2/go.mod h1:dIW8puxSbYLSPv/ju0d9A3CpwXdtqvJtYKDMVmPLOWE=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.9 h1:ramlTFqWSsOt4Y/skpd30D8oI0kfKf5wd1Yu9C5HhPw=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.9/go.mod h1:+B//vxKaB6Z/HfJfRV4ikLz0M7nIcKheHKm96FuaRrs=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3/go.mod h1:wlY6SVjuwvh3TVRpTqdy4I1JpBFLX4UGeKZdWntaocw=
@@ -931,8 +931,8 @@ github.com/aws/aws-sdk-go-v2/service/lambda v1.50.0 h1:fBJs+X3ZOEqpmiSb7as6DBqm7
github.com/aws/aws-sdk-go-v2/service/lambda v1.50.0/go.mod h1:yEO3Ejj0qBhdIDlRYQ8O9+gB5CAUKyaYYiFBkvGX8ZA=
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3/go.mod h1:g1qvDuRsJY+XghsV6zg00Z4KJ7DtFFCx8fJD2a491Ak=
github.com/aws/aws-sdk-go-v2/service/s3 v1.43.0/go.mod h1:NXRKkiRF+erX2hnybnVU660cYT5/KChRD4iUgJ97cI8=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.73.1 h1:OzmyfYGiMCOIAq5pa0KWcaZoA9F8FqajOJevh+hhFdY=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.73.1/go.mod h1:K+0a0kWDHAUXBH8GvYGS3cQRwIuRjO9bMWUz6vpNCaU=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2 h1:F3h8VYq9ZLBXYurmwrT8W0SPhgCcU0q+0WZJfT1dFt0=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2/go.mod h1:jGJ/v7FIi7Ys9t54tmEFnrxuaWeJLpwNgKp2DXAVhOU=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.4/go.mod h1:PJc8s+lxyU8rrre0/4a0pn2wgwiDvOEzoOjcJUBr67o=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.5 h1:gqj99GNYzuY0jMekToqvOW1VaSupY0Qn0oj1JGSolpE=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.5/go.mod h1:FTCjaQxTVVQqLQ4ktBsLNZPnJ9pVLkJ6F0qVwtALaxk=
@@ -945,19 +945,19 @@ github.com/aws/aws-sdk-go-v2/service/sqs v1.29.7/go.mod h1:8GWUDux5Z2h6z2efAtr54
github.com/aws/aws-sdk-go-v2/service/ssm v1.24.1/go.mod h1:NR/xoKjdbRJ+qx0pMR4mI+N/H1I1ynHwXnO6FowXJc0=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.3/go.mod h1:7UQ/e69kU7LDPtY40OyoHYgRmgfGM4mgsLYtcObdveU=
github.com/aws/aws-sdk-go-v2/service/sso v1.17.2/go.mod h1:/pE21vno3q1h4bbhUOEi+6Zu/aT26UK2WKkDXd+TssQ=
-github.com/aws/aws-sdk-go-v2/service/sso v1.24.10 h1:DyZUj3xSw3FR3TXSwDhPhuZkkT14QHBiacdbUVcD0Dg=
-github.com/aws/aws-sdk-go-v2/service/sso v1.24.10/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 h1:kuIyu4fTT38Kj7YCC7ouNbVZSSpqkZ+LzIfhCr6Dg+I=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.11/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.0/go.mod h1:dWqm5G767qwKPuayKfzm4rjzFmVjiBFbOJrpSPnAMDs=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9 h1:I1TsPEs34vbpOnR81GIcAq4/3Ud+jRHVGwx6qLQUHLs=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9/go.mod h1:Fzsj6lZEb8AkTE5S68OhcbBqeWPsR8RnGuKPr8Todl8=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 h1:l+dgv/64iVlQ3WsBbnn+JSbkj01jIi+SM0wYsj3y/hY=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10/go.mod h1:Fzsj6lZEb8AkTE5S68OhcbBqeWPsR8RnGuKPr8Todl8=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.3/go.mod h1:bfBj0iVmsUyUg4weDB4NxktD9rDGeKSVWnjTnwbx9b8=
github.com/aws/aws-sdk-go-v2/service/sts v1.25.3/go.mod h1:4EqRHDCKP78hq3zOnmFXu5k0j4bXbRFfCh/zQ6KnEfQ=
-github.com/aws/aws-sdk-go-v2/service/sts v1.33.8 h1:pqEJQtlKWvnv3B6VRt60ZmsHy3SotlEBvfUBPB1KVcM=
-github.com/aws/aws-sdk-go-v2/service/sts v1.33.8/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw=
+github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 h1:BRVDbewN6VZcwr+FBOszDKvYeXY1kJ+GGMCcpghlw0U=
+github.com/aws/aws-sdk-go-v2/service/sts v1.33.9/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw=
github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
-github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
-github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
+github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
+github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
@@ -2276,8 +2276,8 @@ go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
-go.temporal.io/api v1.43.1 h1:44Q12pUczfGkcAwZtJNhfv3+L6RFzL3kNk547/r8QY8=
-go.temporal.io/api v1.43.1/go.mod h1:1WwYUMo6lao8yl0371xWUm13paHExN5ATYT/B7QtFis=
+go.temporal.io/api v1.43.2 h1:cHuAxZOgxpgwXH8nVEAWW6KS+QPGY2X0JWVjW7+RHOQ=
+go.temporal.io/api v1.43.2/go.mod h1:1WwYUMo6lao8yl0371xWUm13paHExN5ATYT/B7QtFis=
go.temporal.io/sdk v1.32.1 h1:slA8prhdFr4lxpsTcRusWVitD/cGjELfKUh0mBj73SU=
go.temporal.io/sdk v1.32.1/go.mod h1:8U8H7rF9u4Hyb4Ry9yiEls5716DHPNvVITPNkgWUwE8=
go.temporal.io/sdk/contrib/opentelemetry v0.6.0 h1:rNBArDj5iTUkcMwKocUShoAW59o6HdS7Nq4CTp4ldj8=
@@ -2853,8 +2853,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
-google.golang.org/api v0.217.0 h1:GYrUtD289o4zl1AhiTZL0jvQGa2RDLyC+kX1N/lfGOU=
-google.golang.org/api v0.217.0/go.mod h1:qMc2E8cBAbQlRypBTBWHklNJlaZZJBwDv81B1Iu8oSI=
+google.golang.org/api v0.218.0 h1:x6JCjEWeZ9PFCRe9z0FBrNwj7pB7DOAqT35N+IPnAUA=
+google.golang.org/api v0.218.0/go.mod h1:5VGHBAkxrA/8EFjLVEYmMUJ8/8+gWWQ3s4cFH0FxG2M=
google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
diff --git a/internal/benthos/benthos-builder/builders/processors.go b/internal/benthos/benthos-builder/builders/processors.go
index deb77ef9d1..b2bd8c54d2 100644
--- a/internal/benthos/benthos-builder/builders/processors.go
+++ b/internal/benthos/benthos-builder/builders/processors.go
@@ -8,7 +8,6 @@ import (
"fmt"
"slices"
"strings"
- "unicode"
"connectrpc.com/connect"
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
@@ -16,6 +15,7 @@ import (
sqlmanager_shared "github.com/nucleuscloud/neosync/backend/pkg/sqlmanager/shared"
tabledependency "github.com/nucleuscloud/neosync/backend/pkg/table-dependency"
bb_internal "github.com/nucleuscloud/neosync/internal/benthos/benthos-builder/internal"
+ javascript_userland "github.com/nucleuscloud/neosync/internal/javascript/userland"
neosync_benthos "github.com/nucleuscloud/neosync/worker/pkg/benthos"
"github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
transformer_utils "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers/utils"
@@ -242,7 +242,7 @@ func extractJsFunctionsAndOutputs(ctx context.Context, transformerclient mgmtv1a
}
if len(jsFunctions) > 0 {
- return constructBenthosJsProcessor(jsFunctions, benthosOutputs), nil
+ return javascript_userland.GetFunction(jsFunctions, benthosOutputs), nil
} else {
return "", nil
}
@@ -385,83 +385,25 @@ func buildRedisGetBranchConfig(
func constructJsFunction(jsCode, col string, source mgmtv1alpha1.TransformerSource) string {
switch source {
case mgmtv1alpha1.TransformerSource_TRANSFORMER_SOURCE_TRANSFORM_JAVASCRIPT:
- return fmt.Sprintf(`
-function fn_%s(value, input){
- %s
-};
-`, sanitizeJsFunctionName(col), jsCode)
+ return javascript_userland.GetTransformJavascriptFunction(jsCode, col, true)
case mgmtv1alpha1.TransformerSource_TRANSFORMER_SOURCE_GENERATE_JAVASCRIPT:
- return fmt.Sprintf(`
-function fn_%s(){
- %s
-};
-`, sanitizeJsFunctionName(col), jsCode)
+ return javascript_userland.GetGenerateJavascriptFunction(jsCode, col)
default:
return ""
}
}
-func sanitizeJsFunctionName(input string) string {
- var result strings.Builder
-
- for i, r := range input {
- if unicode.IsLetter(r) || r == '_' || r == '$' || (unicode.IsDigit(r) && i > 0) {
- result.WriteRune(r)
- } else if unicode.IsDigit(r) && i == 0 {
- result.WriteRune('_')
- result.WriteRune(r)
- } else {
- result.WriteRune('_')
- }
- }
-
- return result.String()
-}
-
-func constructBenthosJsProcessor(jsFunctions, benthosOutputs []string) string {
- jsFunctionStrings := strings.Join(jsFunctions, "\n")
-
- benthosOutputString := strings.Join(benthosOutputs, "\n")
-
- jsCode := fmt.Sprintf(`
-(() => {
-%s
-const input = benthos.v0_msg_as_structured();
-const updatedValues = {}
-%s
-neosync.patchStructuredMessage(updatedValues)
-})();`, jsFunctionStrings, benthosOutputString)
- return jsCode
-}
-
func constructBenthosJavascriptObject(col string, source mgmtv1alpha1.TransformerSource) string {
switch source {
case mgmtv1alpha1.TransformerSource_TRANSFORMER_SOURCE_TRANSFORM_JAVASCRIPT:
- return fmt.Sprintf(
- `updatedValues[%q] = fn_%s(%s, input)`,
- col,
- sanitizeJsFunctionName(col),
- convertJsObjPathToOptionalChain(fmt.Sprintf("input.%s", col)),
- )
+ return javascript_userland.BuildOutputSetter(col, true, true)
case mgmtv1alpha1.TransformerSource_TRANSFORMER_SOURCE_GENERATE_JAVASCRIPT:
- return fmt.Sprintf(
- `updatedValues[%q] = fn_%s()`,
- col,
- sanitizeJsFunctionName(col),
- )
+ return javascript_userland.BuildOutputSetter(col, false, false)
default:
return ""
}
}
-func convertJsObjPathToOptionalChain(inputPath string) string {
- parts := strings.Split(inputPath, ".")
- for i := 1; i < len(parts); i++ {
- parts[i] = fmt.Sprintf("['%s']", parts[i])
- }
- return strings.Join(parts, "?.")
-}
-
// takes in an user defined config with just an id field and return the right transformer config for that user defined function id
func convertUserDefinedFunctionConfig(
ctx context.Context,
@@ -479,11 +421,6 @@ func convertUserDefinedFunctionConfig(
}, nil
}
-/*
-function transformers
-root.{destination_col} = transformerfunction(args)
-*/
-
func computeMutationFunction(col *mgmtv1alpha1.JobMapping, colInfo *sqlmanager_shared.DatabaseSchemaRow, splitColumnPath bool) (string, error) {
var maxLen int64 = 10000
if colInfo != nil && colInfo.CharacterMaximumLength > 0 {
diff --git a/internal/benthos/benthos-builder/builders/processors_test.go b/internal/benthos/benthos-builder/builders/processors_test.go
index e01ac04f75..a113a7a019 100644
--- a/internal/benthos/benthos-builder/builders/processors_test.go
+++ b/internal/benthos/benthos-builder/builders/processors_test.go
@@ -14,35 +14,6 @@ import (
"github.com/stretchr/testify/require"
)
-func Test_sanitizeFunctionName(t *testing.T) {
- tests := []struct {
- input string
- expected string
- }{
- {"123my Function!", "_123my_Function_"},
- {"validName", "validName"},
- {"name_with_underscores", "name_with_underscores"},
- {"$dollarSign", "$dollarSign"},
- {"invalid-char$", "invalid_char$"},
- {"spaces in name", "spaces_in_name"},
- {"!@#$%^&*()_+=", "___$_________"},
- {"_leadingUnderscore", "_leadingUnderscore"},
- {"$startingDollarSign", "$startingDollarSign"},
- {"endingWithNumber1", "endingWithNumber1"},
- {"functionName123", "functionName123"},
- {"ä¸æ–‡å—符", "ä¸æ–‡å—符"},
- }
-
- for _, tt := range tests {
- t.Run(tt.input, func(t *testing.T) {
- actual := sanitizeJsFunctionName(tt.input)
- if actual != tt.expected {
- t.Errorf("sanitizeJsFunctionName(%q) = %q; expected %q", tt.input, actual, tt.expected)
- }
- })
- }
-}
-
func Test_buildProcessorConfigsJavascript(t *testing.T) {
mockTransformerClient := mgmtv1alpha1connect.NewMockTransformersServiceClient(t)
diff --git a/internal/benthos_slogger/logger.go b/internal/benthos_slogger/logger.go
new file mode 100644
index 0000000000..73d0828c55
--- /dev/null
+++ b/internal/benthos_slogger/logger.go
@@ -0,0 +1,93 @@
+package benthos_slogger
+
+import (
+ "context"
+ "log/slog"
+
+ "github.com/warpstreamlabs/bento/public/service"
+)
+
+var _ slog.Handler = (*benthosLogHandler)(nil)
+
+type benthosLogHandler struct {
+ logger *service.Logger
+ attrs []slog.Attr
+ groups []string
+}
+
+func (h *benthosLogHandler) Enabled(ctx context.Context, level slog.Level) bool {
+ // We defer to the benthos logger and let it handle what leveling it wants to output
+ return true
+}
+
+func (h *benthosLogHandler) Handle(ctx context.Context, r slog.Record) error { //nolint:gocritic // Needs to conform to the slog.Handler interface
+ // Combine pre-defined attrs with record attrs
+ allAttrs := make([]slog.Attr, 0, len(h.attrs)+r.NumAttrs())
+ allAttrs = append(allAttrs, h.attrs...)
+
+ r.Attrs(func(attr slog.Attr) bool {
+ if !attr.Equal(slog.Attr{}) {
+ // Handle groups
+ if len(h.groups) > 0 {
+ last := h.groups[len(h.groups)-1]
+ if last != "" {
+ attr.Key = last + "." + attr.Key
+ }
+ }
+ allAttrs = append(allAttrs, attr)
+ }
+ return true
+ })
+
+ // Convert to key-value pairs for temporal logger
+ keyvals := make([]any, 0, len(allAttrs)*2)
+ for _, attr := range allAttrs {
+ keyvals = append(keyvals, attr.Key, attr.Value.Any())
+ }
+
+ switch r.Level {
+ case slog.LevelDebug:
+ h.logger.With(keyvals...).Debug(r.Message)
+ case slog.LevelInfo:
+ h.logger.With(keyvals...).Info(r.Message)
+ case slog.LevelWarn:
+ h.logger.With(keyvals...).Warn(r.Message)
+ case slog.LevelError:
+ h.logger.With(keyvals...).Error(r.Message)
+ }
+ return nil
+}
+
+func (h *benthosLogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ newAttrs := []slog.Attr{}
+ newAttrs = append(newAttrs, h.attrs...)
+ newAttrs = append(newAttrs, attrs...)
+ return &benthosLogHandler{
+ logger: h.logger,
+ attrs: newAttrs,
+ groups: h.groups,
+ }
+}
+
+func (h *benthosLogHandler) WithGroup(name string) slog.Handler {
+ if name == "" {
+ return h
+ }
+ newGroups := []string{}
+ newGroups = append(newGroups, h.groups...)
+ newGroups = append(newGroups, name)
+ return &benthosLogHandler{
+ logger: h.logger,
+ attrs: h.attrs,
+ groups: newGroups,
+ }
+}
+
+func newBenthosLogHandler(logger *service.Logger) *benthosLogHandler {
+ return &benthosLogHandler{logger: logger}
+}
+
+// Returns a benthos logger wrapped as a slog.Logger to ease plugging in to the rest of the system
+func NewSlogger(logger *service.Logger) *slog.Logger {
+ return slog.New(newBenthosLogHandler(logger))
+}
diff --git a/internal/javascript/functions/benthos/functions.go b/internal/javascript/functions/benthos/functions.go
new file mode 100644
index 0000000000..064a676885
--- /dev/null
+++ b/internal/javascript/functions/benthos/functions.go
@@ -0,0 +1,170 @@
+package benthos_functions
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "log/slog"
+ "net/http"
+ "strings"
+
+ "github.com/dop251/goja"
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+)
+
+const (
+ namespace = "benthos"
+)
+
+func Get() []*javascript_functions.FunctionDefinition {
+ return []*javascript_functions.FunctionDefinition{
+ getV0Fetch(namespace),
+ getV0MsgSetString(namespace),
+ getV0MsgAsString(namespace),
+ getV0MsgSetStructured(namespace),
+ getV0MsgAsStructured(namespace),
+ getV0MsgSetMeta(namespace),
+ getV0MsgGetMeta(namespace),
+ getV0MsgMetaExists(namespace),
+ }
+}
+
+func getV0Fetch(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_fetch", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var (
+ url string
+ httpHeaders map[string]any
+ method = "GET"
+ payload = ""
+ )
+ if err := javascript_functions.ParseFunctionArguments(call, &url, &httpHeaders, &method, &payload); err != nil {
+ return nil, err
+ }
+
+ var payloadReader io.Reader
+ if payload != "" {
+ payloadReader = strings.NewReader(payload)
+ }
+
+ req, err := http.NewRequestWithContext(ctx, method, url, payloadReader)
+ if err != nil {
+ return nil, err
+ }
+
+ // Parse HTTP headers
+ for k, v := range httpHeaders {
+ vStr, _ := v.(string)
+ req.Header.Add(k, vStr)
+ }
+
+ // Do request
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ respBody, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ return map[string]any{
+ "status": resp.StatusCode,
+ "body": string(respBody),
+ }, nil
+ }
+ })
+}
+
+func getV0MsgSetString(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_set_string", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var value string
+ if err := javascript_functions.ParseFunctionArguments(call, &value); err != nil {
+ return nil, err
+ }
+
+ r.ValueApi().SetBytes([]byte(value))
+ return nil, nil
+ }
+ })
+}
+
+func getV0MsgAsString(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_as_string", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ b, err := r.ValueApi().AsBytes()
+ if err != nil {
+ return nil, err
+ }
+ return string(b), nil
+ }
+ })
+}
+
+func getV0MsgSetStructured(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_set_structured", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var value any
+ if err := javascript_functions.ParseFunctionArguments(call, &value); err != nil {
+ return nil, err
+ }
+
+ r.ValueApi().SetStructured(value)
+ return nil, nil
+ }
+ })
+}
+
+func getV0MsgAsStructured(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_as_structured", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ return r.ValueApi().AsStructured()
+ }
+ })
+}
+
+func getV0MsgSetMeta(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_set_meta", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var key string
+ var value any
+ if err := javascript_functions.ParseFunctionArguments(call, &key, &value); err != nil {
+ return nil, err
+ }
+ r.ValueApi().MetaSetMut(key, value)
+ return nil, nil
+ }
+ })
+}
+
+func getV0MsgGetMeta(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_get_meta", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var key string
+ if err := javascript_functions.ParseFunctionArguments(call, &key); err != nil {
+ return nil, err
+ }
+ result, ok := r.ValueApi().MetaGet(key)
+ if !ok {
+ return nil, fmt.Errorf("key %s not found", key)
+ }
+ return result, nil
+ }
+ })
+}
+
+func getV0MsgMetaExists(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "v0_msg_exists_meta", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var key string
+ if err := javascript_functions.ParseFunctionArguments(call, &key); err != nil {
+ return nil, err
+ }
+ _, ok := r.ValueApi().MetaGet(key)
+ return ok, nil
+ }
+ })
+}
diff --git a/internal/javascript/functions/benthos/functions_test.go b/internal/javascript/functions/benthos/functions_test.go
new file mode 100644
index 0000000000..2a1aaefee2
--- /dev/null
+++ b/internal/javascript/functions/benthos/functions_test.go
@@ -0,0 +1,12 @@
+package benthos_functions
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestGet(t *testing.T) {
+ functions := Get()
+ require.NotEmpty(t, functions)
+}
diff --git a/internal/javascript/functions/functions.go b/internal/javascript/functions/functions.go
new file mode 100644
index 0000000000..3b71779d74
--- /dev/null
+++ b/internal/javascript/functions/functions.go
@@ -0,0 +1,139 @@
+package javascript_functions
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log/slog"
+
+ "github.com/dop251/goja"
+)
+
+type Runner interface {
+ ValueApi() ValueApi
+}
+
+type ValueApi interface {
+ SetBytes(value []byte)
+ AsBytes() ([]byte, error)
+ SetStructured(value any)
+ AsStructured() (any, error)
+
+ MetaGet(name string) (any, bool)
+ MetaSetMut(name string, value any)
+}
+
+type Ctor func(r Runner) Function
+
+type FunctionDefinition struct {
+ namespace string
+ name string
+ // ctor means "constructor"
+ ctor Ctor
+}
+
+func NewFunctionDefinition(namespace, name string, ctor Ctor) *FunctionDefinition {
+ return &FunctionDefinition{
+ namespace: namespace,
+ name: name,
+ ctor: ctor,
+ }
+}
+
+func (f *FunctionDefinition) Namespace() string {
+ return f.namespace
+}
+
+func (f *FunctionDefinition) Name() string {
+ return f.name
+}
+
+func (f *FunctionDefinition) Ctor() Ctor {
+ return f.ctor
+}
+
+type Function func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error)
+
+// Takes in a goja function call and returns the parsed arguments into the provided pointers.
+// Returns an error if the arguments are not of the expected type.
+func ParseFunctionArguments(call goja.FunctionCall, ptrs ...any) error {
+ if len(ptrs) < len(call.Arguments) {
+ return fmt.Errorf("have %d arguments, but only %d pointers to parse into", len(call.Arguments), len(ptrs))
+ }
+
+ for i := 0; i < len(call.Arguments); i++ {
+ arg, ptr := call.Argument(i), ptrs[i]
+
+ if goja.IsUndefined(arg) {
+ return fmt.Errorf("argument at position %d is undefined", i)
+ }
+
+ var err error
+ switch p := ptr.(type) {
+ case *string:
+ *p = arg.String()
+ case *int:
+ *p = int(arg.ToInteger())
+ case *int64:
+ *p = arg.ToInteger()
+ case *float64:
+ *p = arg.ToFloat()
+ case *map[string]any:
+ *p, err = getMapFromValue(arg)
+ case *bool:
+ *p = arg.ToBoolean()
+ case *[]any:
+ *p, err = getSliceFromValue(arg)
+ case *[]map[string]any:
+ *p, err = getMapSliceFromValue(arg)
+ case *goja.Value:
+ *p = arg
+ case *any:
+ *p = arg.Export()
+ default:
+ return fmt.Errorf("encountered unhandled type %T while trying to parse %v into %v", arg.ExportType().String(), arg, p)
+ }
+ if err != nil {
+ return fmt.Errorf("could not parse %v (%s) into %v (%T): %v", arg, arg.ExportType().String(), ptr, ptr, err)
+ }
+ }
+
+ return nil
+}
+
+func getMapFromValue(val goja.Value) (map[string]any, error) {
+ outVal := val.Export()
+ v, ok := outVal.(map[string]any)
+ if !ok {
+ return nil, errors.New("value is not of type map")
+ }
+ return v, nil
+}
+
+func getSliceFromValue(val goja.Value) ([]any, error) {
+ outVal := val.Export()
+ v, ok := outVal.([]any)
+ if !ok {
+ return nil, errors.New("value is not of type slice")
+ }
+ return v, nil
+}
+
+func getMapSliceFromValue(val goja.Value) ([]map[string]any, error) {
+ outVal := val.Export()
+ if v, ok := outVal.([]map[string]any); ok {
+ return v, nil
+ }
+ vSlice, ok := outVal.([]any)
+ if !ok {
+ return nil, errors.New("value is not of type map slice")
+ }
+ v := make([]map[string]any, len(vSlice))
+ for i, e := range vSlice {
+ v[i], ok = e.(map[string]any)
+ if !ok {
+ return nil, errors.New("value is not of type map slice")
+ }
+ }
+ return v, nil
+}
diff --git a/internal/javascript/functions/neosync/functions.go b/internal/javascript/functions/neosync/functions.go
new file mode 100644
index 0000000000..6e41f218c6
--- /dev/null
+++ b/internal/javascript/functions/neosync/functions.go
@@ -0,0 +1,138 @@
+package neosync_functions
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+ "strings"
+
+ "github.com/dop251/goja"
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+ "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
+)
+
+const (
+ namespace = "neosync"
+)
+
+func Get() ([]*javascript_functions.FunctionDefinition, error) {
+ generatorFns, err := getNeosyncGenerators()
+ if err != nil {
+ return nil, err
+ }
+ transformerFns, err := getNeosyncTransformers()
+ if err != nil {
+ return nil, err
+ }
+ patchStructuredMessage := getPatchStructuredMessage(namespace)
+
+ output := make([]*javascript_functions.FunctionDefinition, 0, len(generatorFns)+len(transformerFns)+1)
+ output = append(output, generatorFns...)
+ output = append(output, transformerFns...)
+ output = append(output, patchStructuredMessage)
+ return output, nil
+}
+
+func getPatchStructuredMessage(namespace string) *javascript_functions.FunctionDefinition {
+ return javascript_functions.NewFunctionDefinition(namespace, "patchStructuredMessage", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var updates map[string]any
+ if err := javascript_functions.ParseFunctionArguments(call, &updates); err != nil {
+ return nil, err
+ }
+
+ originalData, err := r.ValueApi().AsStructured()
+ if err != nil {
+ return nil, fmt.Errorf("failed to get structured data: %w", err)
+ }
+
+ originalMap, ok := originalData.(map[string]any)
+ if !ok {
+ return nil, fmt.Errorf("structured data is not a map")
+ }
+
+ for key, value := range updates {
+ setNestedProperty(originalMap, key, value)
+ }
+
+ r.ValueApi().SetStructured(originalMap)
+
+ return nil, nil
+ }
+ })
+}
+
+func setNestedProperty(obj map[string]any, path string, value any) {
+ parts := strings.Split(path, ".")
+ current := obj
+
+ for i, part := range parts {
+ if i == len(parts)-1 {
+ current[part] = value
+ } else {
+ if _, ok := current[part]; !ok {
+ current[part] = make(map[string]any)
+ }
+ current = current[part].(map[string]any)
+ }
+ }
+}
+
+func getNeosyncGenerators() ([]*javascript_functions.FunctionDefinition, error) {
+ generators := transformers.GetNeosyncGenerators()
+ fns := make([]*javascript_functions.FunctionDefinition, 0, len(generators))
+ for _, f := range generators {
+ templateData, err := f.GetJsTemplateData()
+ if err != nil {
+ return nil, err
+ }
+
+ fn := javascript_functions.NewFunctionDefinition(namespace, templateData.Name, func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var (
+ opts map[string]any
+ )
+ if err := javascript_functions.ParseFunctionArguments(call, &opts); err != nil {
+ return nil, err
+ }
+ goOpts, err := f.ParseOptions(opts)
+ if err != nil {
+ return nil, err
+ }
+ return f.Generate(goOpts)
+ }
+ })
+ fns = append(fns, fn)
+ }
+ return fns, nil
+}
+
+func getNeosyncTransformers() ([]*javascript_functions.FunctionDefinition, error) {
+ neosyncTransformers := transformers.GetNeosyncTransformers()
+ fns := make([]*javascript_functions.FunctionDefinition, 0, len(neosyncTransformers))
+ for _, f := range neosyncTransformers {
+ templateData, err := f.GetJsTemplateData()
+ if err != nil {
+ return nil, err
+ }
+
+ fn := javascript_functions.NewFunctionDefinition(namespace, templateData.Name, func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ var (
+ value any
+ opts map[string]any
+ )
+ if err := javascript_functions.ParseFunctionArguments(call, &value, &opts); err != nil {
+ return nil, err
+ }
+ goOpts, err := f.ParseOptions(opts)
+ if err != nil {
+ return nil, err
+ }
+ return f.Transform(value, goOpts)
+ }
+ })
+ fns = append(fns, fn)
+ }
+ return fns, nil
+}
diff --git a/worker/pkg/benthos/javascript/functions_test.go b/internal/javascript/functions/neosync/functions_test.go
similarity index 91%
rename from worker/pkg/benthos/javascript/functions_test.go
rename to internal/javascript/functions/neosync/functions_test.go
index 2db19e6556..44390cd17f 100644
--- a/worker/pkg/benthos/javascript/functions_test.go
+++ b/internal/javascript/functions/neosync/functions_test.go
@@ -1,4 +1,4 @@
-package javascript
+package neosync_functions
import (
"testing"
@@ -6,6 +6,12 @@ import (
"github.com/stretchr/testify/require"
)
+func TestGet(t *testing.T) {
+ functions, err := Get()
+ require.NoError(t, err)
+ require.NotEmpty(t, functions)
+}
+
func Test_setNestedProperty(t *testing.T) {
t.Run("Set simple property", func(t *testing.T) {
obj := make(map[string]any)
diff --git a/internal/javascript/javascript.go b/internal/javascript/javascript.go
new file mode 100644
index 0000000000..7caf6d93b8
--- /dev/null
+++ b/internal/javascript/javascript.go
@@ -0,0 +1,52 @@
+package javascript
+
+import (
+ "log/slog"
+
+ goja_require "github.com/dop251/goja_nodejs/require"
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+ benthos_functions "github.com/nucleuscloud/neosync/internal/javascript/functions/benthos"
+ neosync_functions "github.com/nucleuscloud/neosync/internal/javascript/functions/neosync"
+ javascript_vm "github.com/nucleuscloud/neosync/internal/javascript/vm"
+)
+
+// Comes full featured, but expects a value api that the benthos/neosync functions can manipulate
+func NewDefaultValueRunner(
+ valueApi javascript_functions.ValueApi,
+ logger *slog.Logger,
+) (*javascript_vm.Runner, error) {
+ functions, err := getDefaultFunctions()
+ if err != nil {
+ return nil, err
+ }
+ return javascript_vm.NewRunner(
+ javascript_vm.WithValueApi(valueApi),
+ javascript_vm.WithLogger(logger),
+ javascript_vm.WithConsole(),
+ javascript_vm.WithJsRegistry(goja_require.NewRegistry()),
+ javascript_vm.WithFunctions(functions...),
+ )
+}
+
+// Comes full featured but does not register any custom functions
+func NewDefaultRunner(
+ logger *slog.Logger,
+) (*javascript_vm.Runner, error) {
+ return javascript_vm.NewRunner(
+ javascript_vm.WithLogger(logger),
+ javascript_vm.WithConsole(),
+ javascript_vm.WithJsRegistry(goja_require.NewRegistry()),
+ )
+}
+
+func getDefaultFunctions() ([]*javascript_functions.FunctionDefinition, error) {
+ benthosFns := benthos_functions.Get()
+ neosyncFns, err := neosync_functions.Get()
+ if err != nil {
+ return nil, err
+ }
+ output := make([]*javascript_functions.FunctionDefinition, 0, len(benthosFns)+len(neosyncFns))
+ output = append(output, benthosFns...)
+ output = append(output, neosyncFns...)
+ return output, nil
+}
diff --git a/internal/javascript/userland/userland.go b/internal/javascript/userland/userland.go
new file mode 100644
index 0000000000..537fab446a
--- /dev/null
+++ b/internal/javascript/userland/userland.go
@@ -0,0 +1,124 @@
+package javascript_userland
+
+import (
+ "fmt"
+ "strings"
+ "unicode"
+
+ "github.com/google/uuid"
+)
+
+// GetGenerateJavascriptFunction returns a Javascript function that takes no inputs and generates a value
+// fnNameSuffix is the suffix of the function name
+func GetGenerateJavascriptFunction(jsCode, fnNameSuffix string) string {
+ return fmt.Sprintf(`
+function fn_%s(){
+ %s
+};
+`, sanitizeFunctionName(fnNameSuffix), jsCode)
+}
+
+// GetTransformJavascriptFunction returns a Javascript function that takes a value and input and returns a transformed value
+// fnNameSuffix is the suffix of the function name
+// includeRecord is true if the function should take in the input record
+func GetTransformJavascriptFunction(jsCode, fnNameSuffix string, includeRecord bool) string {
+ if includeRecord {
+ return fmt.Sprintf(`
+function fn_%s(value, input){
+ %s
+};
+`, sanitizeFunctionName(fnNameSuffix), jsCode)
+ }
+
+ return fmt.Sprintf(`
+function fn_%s(value){
+ %s
+};
+`, sanitizeFunctionName(fnNameSuffix), jsCode)
+}
+
+func sanitizeFunctionName(input string) string {
+ var result strings.Builder
+
+ for i, r := range input {
+ if unicode.IsLetter(r) || r == '_' || r == '$' || (unicode.IsDigit(r) && i > 0) {
+ result.WriteRune(r)
+ } else if unicode.IsDigit(r) && i == 0 {
+ result.WriteRune('_')
+ result.WriteRune(r)
+ } else {
+ result.WriteRune('_')
+ }
+ }
+
+ return result.String()
+}
+
+// Takes a userland function and returns a single function that can be invoked by the JS VM
+// Returns the property key that the output will be set to
+func GetSingleGenerateFunction(userCode string) (code, propertyPath string) {
+ propertyPath = uuid.NewString()
+ fn := GetGenerateJavascriptFunction(userCode, propertyPath)
+ outputSetter := BuildOutputSetter(propertyPath, false, false)
+ return GetFunction([]string{fn}, []string{outputSetter}), propertyPath
+}
+
+// Takes a userland function and returns a single function that can be invoked by the JS VM
+// Returns the property key that the output will be set to
+func GetSingleTransformFunction(userCode string) (code, propertyPath string) {
+ propertyPath = uuid.NewString()
+ fn := GetTransformJavascriptFunction(userCode, propertyPath, false)
+ outputSetter := BuildOutputSetter(propertyPath, true, false)
+ return GetFunction([]string{fn}, []string{outputSetter}), propertyPath
+}
+
+// Takes all of the built userland functions and output setters and stuffs them into a single function that can be invoked by the JS VM
+// Calling the resulting program expects benthos.v0_msg_as_structured() and neosync.patchStructuredMessage() to be defined in the JS VM
+func GetFunction(jsFuncs, outputSetters []string) string {
+ jsFunctionStrings := strings.Join(jsFuncs, "\n")
+
+ benthosOutputString := strings.Join(outputSetters, "\n")
+
+ jsCode := fmt.Sprintf(`
+(() => {
+%s
+const input = benthos.v0_msg_as_structured();
+const updatedValues = {}
+%s
+neosync.patchStructuredMessage(updatedValues)
+})();`, jsFunctionStrings, benthosOutputString)
+ return jsCode
+}
+
+// BuildOutputSetter builds a string that sets the output of the function to the property path on the "updatedValues" object
+// includeInput is true if the propertyPath's value should be passed to the function
+// includeInputRecord is true if the entire "input" object should be passed to the function as the second argument
+func BuildOutputSetter(propertyPath string, includeInput, includeInputRecord bool) string {
+ if includeInput {
+ var strTemplate string
+ if includeInputRecord {
+ strTemplate = `updatedValues[%q] = fn_%s(%s, input)`
+ } else {
+ strTemplate = `updatedValues[%q] = fn_%s(%s)`
+ }
+ return fmt.Sprintf(
+ strTemplate,
+ propertyPath,
+ sanitizeFunctionName(propertyPath),
+ convertJsObjPathToOptionalChain(fmt.Sprintf("input.%s", propertyPath)),
+ )
+ }
+ return fmt.Sprintf(
+ `updatedValues[%q] = fn_%s()`,
+ propertyPath,
+ sanitizeFunctionName(propertyPath),
+ )
+}
+
+func convertJsObjPathToOptionalChain(inputPath string) string {
+ parts := strings.Split(inputPath, ".")
+ for i := 1; i < len(parts); i++ {
+ parts[i] = fmt.Sprintf("['%s']", parts[i])
+ }
+ return strings.Join(parts, "?.")
+}
diff --git a/internal/javascript/userland/userland_test.go b/internal/javascript/userland/userland_test.go
new file mode 100644
index 0000000000..2332fd72c5
--- /dev/null
+++ b/internal/javascript/userland/userland_test.go
@@ -0,0 +1,369 @@
+package javascript_userland
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/dop251/goja"
+ "github.com/stretchr/testify/require"
+)
+
+func Test_sanitizeFunctionName(t *testing.T) {
+ tests := []struct {
+ input string
+ expected string
+ }{
+ {"123my Function!", "_123my_Function_"},
+ {"validName", "validName"},
+ {"name_with_underscores", "name_with_underscores"},
+ {"$dollarSign", "$dollarSign"},
+ {"invalid-char$", "invalid_char$"},
+ {"spaces in name", "spaces_in_name"},
+ {"!@#$%^&*()_+=", "___$_________"},
+ {"_leadingUnderscore", "_leadingUnderscore"},
+ {"$startingDollarSign", "$startingDollarSign"},
+ {"endingWithNumber1", "endingWithNumber1"},
+ {"functionName123", "functionName123"},
+ {"ä¸æ–‡å—符", "ä¸æ–‡å—符"},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.input, func(t *testing.T) {
+ actual := sanitizeFunctionName(tt.input)
+ if actual != tt.expected {
+ t.Errorf("sanitizeJsFunctionName(%q) = %q; expected %q", tt.input, actual, tt.expected)
+ }
+ })
+ }
+}
+
+func Test_GetSingleGenerateFunction(t *testing.T) {
+ t.Parallel()
+ t.Run("string", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return 'hello world';")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, "hello world")
+ })
+ t.Run("number", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return 123;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, int64(123))
+ })
+
+ t.Run("boolean", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return true;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, true)
+ })
+
+ t.Run("object", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return {a: 1, b: 2};")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, map[string]any{"a": int64(1), "b": int64(2)})
+ })
+
+ t.Run("array", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return [1, 2, 3];")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, []any{int64(1), int64(2), int64(3)})
+ })
+
+ t.Run("null", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return null;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, nil)
+ })
+ t.Run("undefined", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleGenerateFunction("return undefined;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, nil)
+ })
+}
+
+func Test_GetSingleTransformFunction(t *testing.T) {
+ t.Parallel()
+ t.Run("string", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return 'hello ' + value;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: "world"}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, "hello world")
+ })
+
+ t.Run("number", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return value + 1;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: 123}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, int64(124))
+ })
+
+ t.Run("boolean", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return !value;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: true}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, false)
+ })
+
+ t.Run("object", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return { ...value, c: 3 };")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: {a: 1, b: 2}}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, map[string]any{"a": int64(1), "b": int64(2), "c": int64(3)})
+ })
+
+ t.Run("array", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return [...value, 3];")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: [1, 2]}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, []any{int64(1), int64(2), int64(3)})
+ })
+
+ t.Run("null", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return value;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: null}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, nil)
+ })
+ t.Run("undefined", func(t *testing.T) {
+ t.Parallel()
+ code, propertyPath := GetSingleTransformFunction("return value;")
+ require.NotEmpty(t, code)
+ require.NotEmpty(t, propertyPath)
+
+ wrappedCode := fmt.Sprintf(`
+ let programOutput = undefined;
+ const benthos = {
+ v0_msg_as_structured: () => ({%q: undefined}),
+ };
+ const neosync = {
+ patchStructuredMessage: (val) => {
+ programOutput = val;
+ }
+ };
+ %s
+ `, propertyPath, code)
+
+ runTestProgram(t, wrappedCode, propertyPath, nil)
+ })
+}
+
+func Test_convertJsObjPathToOptionalChain(t *testing.T) {
+ require.Equal(t, "address", convertJsObjPathToOptionalChain("address"))
+ require.Equal(t, "address?.['city']", convertJsObjPathToOptionalChain("address.city"))
+ require.Equal(t, "address?.['city']?.['state']", convertJsObjPathToOptionalChain("address.city.state"))
+}
+
+func runTestProgram(t testing.TB, code string, propertyPath string, expectedOutput any) {
+ t.Helper()
+ program, err := goja.Compile("test.js", code, true)
+ require.NoError(t, err)
+ rt := goja.New()
+ _, err = rt.RunProgram(program)
+ require.NoError(t, err)
+ programOutput := rt.Get("programOutput").Export()
+ require.NotNil(t, programOutput)
+ outputMap, ok := programOutput.(map[string]any)
+ require.True(t, ok)
+ require.Equal(t, expectedOutput, outputMap[propertyPath])
+}
diff --git a/internal/javascript/vm/console_logger.go b/internal/javascript/vm/console_logger.go
new file mode 100644
index 0000000000..f2c0cfe232
--- /dev/null
+++ b/internal/javascript/vm/console_logger.go
@@ -0,0 +1,34 @@
+package javascript_vm
+
+import (
+ "fmt"
+ "log/slog"
+
+ "github.com/dop251/goja_nodejs/console"
+)
+
+var _ console.Printer = &consoleLogger{}
+
+// adds a standard prefix to the message to make it easier to identify logs that originate from the JS VM.
+const stdPrefix = "[js]: "
+
+func newConsoleLogger(prefix string, logger *slog.Logger) *consoleLogger {
+ return &consoleLogger{prefix: prefix, logger: logger}
+}
+
+type consoleLogger struct {
+ prefix string
+ logger *slog.Logger
+}
+
+func (l *consoleLogger) Log(message string) {
+ l.logger.Info(fmt.Sprintf("%s%s", l.prefix, message))
+}
+
+func (l *consoleLogger) Warn(message string) {
+ l.logger.Warn(fmt.Sprintf("%s%s", l.prefix, message))
+}
+
+func (l *consoleLogger) Error(message string) {
+ l.logger.Error(fmt.Sprintf("%s%s", l.prefix, message))
+}
diff --git a/internal/javascript/vm/vm.go b/internal/javascript/vm/vm.go
new file mode 100644
index 0000000000..ebb1f9c6f3
--- /dev/null
+++ b/internal/javascript/vm/vm.go
@@ -0,0 +1,145 @@
+package javascript_vm
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+ "sync"
+
+ "github.com/dop251/goja"
+ "github.com/dop251/goja_nodejs/console"
+ "github.com/dop251/goja_nodejs/require"
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+)
+
+type Runner struct {
+ vm *goja.Runtime
+ options Options
+ mu sync.Mutex
+}
+
+func (r *Runner) ValueApi() javascript_functions.ValueApi {
+ return r.options.valueApi
+}
+
+type Options struct {
+ logger *slog.Logger
+ requireRegistry *require.Registry
+ functions []*javascript_functions.FunctionDefinition
+ consoleEnabled bool
+ valueApi javascript_functions.ValueApi
+}
+
+type Option func(*Options)
+
+// Sets the value api for the runner
+// This allows custom functions to access an underlying data structure that can be manipulated by the runner
+func WithValueApi(valueApi javascript_functions.ValueApi) Option {
+ return func(opts *Options) {
+ opts.valueApi = valueApi
+ }
+}
+
+// Sets the logger for the runner
+func WithLogger(logger *slog.Logger) Option {
+ return func(opts *Options) {
+ opts.logger = logger
+ }
+}
+
+// Sets the require registry for the runner
+// This allows custom modules to be registered with the runner
+// If the logger is provided, the console module will be registered with the logger
+func WithJsRegistry(registry *require.Registry) Option {
+ return func(opts *Options) {
+ opts.requireRegistry = registry
+ }
+}
+
+// Sets the functions for the runner
+// These functions will be registered with the runner
+// Functions may interact with the value api
+func WithFunctions(functions ...*javascript_functions.FunctionDefinition) Option {
+ return func(opts *Options) {
+ opts.functions = functions
+ }
+}
+
+func WithConsole() Option {
+ return func(opts *Options) {
+ opts.consoleEnabled = true
+ }
+}
+
+// Creates a new JS Runner
+func NewRunner(opts ...Option) (*Runner, error) {
+ options := Options{logger: slog.Default()}
+ for _, opt := range opts {
+ opt(&options)
+ }
+
+ vm := goja.New()
+
+ // if the stars align, we'll register the custom console module with the logger
+ // must come before requireRegistry.Enable()
+ if options.requireRegistry != nil && options.consoleEnabled && options.logger != nil {
+ options.requireRegistry.RegisterNativeModule(console.ModuleName, console.RequireWithPrinter(newConsoleLogger(stdPrefix, options.logger)))
+ }
+
+ if options.requireRegistry != nil {
+ options.requireRegistry.Enable(vm)
+ }
+
+ // must come after requireRegistry.Enable()
+ if options.consoleEnabled {
+ console.Enable(vm)
+ }
+
+ runner := &Runner{
+ vm: vm,
+ options: options,
+ }
+
+ for _, function := range options.functions {
+ if err := registerFunction(runner, function); err != nil {
+ return nil, err
+ }
+ }
+
+ return runner, nil
+}
+
+func (r *Runner) Run(ctx context.Context, program *goja.Program) (goja.Value, error) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ return r.vm.RunProgram(program)
+}
+
+// Registers a custom function with the vm
+func registerFunction(runner *Runner, function *javascript_functions.FunctionDefinition) error {
+ var targetObj *goja.Object
+ if targetObjValue := runner.vm.GlobalObject().Get(function.Namespace()); targetObjValue != nil {
+ targetObj = targetObjValue.ToObject(runner.vm)
+ }
+ if targetObj == nil {
+ if err := runner.vm.GlobalObject().Set(function.Namespace(), map[string]any{}); err != nil {
+ return fmt.Errorf("failed to set global %s object: %w", function.Namespace(), err)
+ }
+ targetObj = runner.vm.GlobalObject().Get(function.Namespace()).ToObject(runner.vm)
+ }
+
+ if err := targetObj.Set(function.Name(), func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
+ l := runner.options.logger.With("function", function.Name())
+ fn := function.Ctor()(runner)
+ result, err := fn(context.Background(), call, rt, l)
+ if err != nil {
+ // This _has_ to be a panic so that the error is properly thrown in the JS runtime
+ // Otherwise things like try/catch will not work properly
+ panic(rt.ToValue(err.Error()))
+ }
+ return rt.ToValue(result)
+ }); err != nil {
+ return fmt.Errorf("failed to set global %s function %v: %w", function.Namespace(), function.Name(), err)
+ }
+ return nil
+}
diff --git a/internal/javascript/vm/vm_test.go b/internal/javascript/vm/vm_test.go
new file mode 100644
index 0000000000..2a657d8c1e
--- /dev/null
+++ b/internal/javascript/vm/vm_test.go
@@ -0,0 +1,91 @@
+package javascript_vm
+
+import (
+ "context"
+ "log/slog"
+ "sync"
+ "testing"
+
+ "github.com/dop251/goja"
+ goja_require "github.com/dop251/goja_nodejs/require"
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+ "github.com/nucleuscloud/neosync/internal/testutil"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestRunner(t *testing.T) {
+ t.Run("basic", func(t *testing.T) {
+ runner, err := NewRunner()
+ require.NoError(t, err)
+
+ program := goja.MustCompile("test.js", "1+1", true)
+ result, err := runner.Run(context.Background(), program)
+ require.NoError(t, err)
+ require.Equal(t, int64(2), result.ToInteger())
+ })
+
+ t.Run("with_console", func(t *testing.T) {
+ runner, err := NewRunner(WithConsole(), WithJsRegistry(goja_require.NewRegistry()))
+ require.NoError(t, err)
+
+ program := goja.MustCompile("test.js", "console.log('hello world')", true)
+ _, err = runner.Run(context.Background(), program)
+ require.NoError(t, err)
+ })
+
+ t.Run("with_console_and_logger", func(t *testing.T) {
+ runner, err := NewRunner(WithConsole(), WithJsRegistry(goja_require.NewRegistry()), WithLogger(testutil.GetTestLogger(t)))
+ require.NoError(t, err)
+
+ program := goja.MustCompile("test.js", `console.log('hello world');`, true)
+ _, err = runner.Run(context.Background(), program)
+ require.NoError(t, err)
+ })
+
+ t.Run("parallel_runs", func(t *testing.T) {
+ runner, err := NewRunner(WithConsole(), WithJsRegistry(goja_require.NewRegistry()), WithLogger(testutil.GetTestLogger(t)))
+ require.NoError(t, err)
+
+ program := goja.MustCompile("test.js", `console.log('hello world');`, true)
+ wg := sync.WaitGroup{}
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ _, err := runner.Run(context.Background(), program)
+ require.NoError(t, err)
+ }()
+ }
+ wg.Wait()
+ })
+
+ t.Run("with_functions", func(t *testing.T) {
+ customFn := javascript_functions.NewFunctionDefinition("test", "test", func(r javascript_functions.Runner) javascript_functions.Function {
+ return func(ctx context.Context, call goja.FunctionCall, rt *goja.Runtime, l *slog.Logger) (any, error) {
+ return "hello world", nil
+ }
+ })
+
+ runner, err := NewRunner(WithFunctions(customFn))
+ require.NoError(t, err)
+
+ program := goja.MustCompile("test.js", `test.test();`, true)
+ result, err := runner.Run(context.Background(), program)
+ require.NoError(t, err)
+ require.Equal(t, "hello world", result.String())
+ })
+}
+
+func BenchmarkRunner_Single(b *testing.B) {
+ runner, err := NewRunner(WithConsole(), WithJsRegistry(goja_require.NewRegistry()), WithLogger(testutil.GetTestLogger(b)))
+ require.NoError(b, err)
+
+ program := goja.MustCompile("test.js", `console.log('hello world');`, true)
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ _, err = runner.Run(context.Background(), program)
+ require.NoError(b, err)
+ }
+}
diff --git a/internal/json-anonymizer/json-anonymizer.go b/internal/json-anonymizer/json-anonymizer.go
index 15f6bbb6c3..c808ace9e4 100644
--- a/internal/json-anonymizer/json-anonymizer.go
+++ b/internal/json-anonymizer/json-anonymizer.go
@@ -12,7 +12,7 @@ import (
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
"github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect"
presidioapi "github.com/nucleuscloud/neosync/internal/ee/presidio"
- transformer "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
+ transformer_executor "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformer_executor"
)
type AnonymizeJsonError struct {
@@ -22,7 +22,7 @@ type AnonymizeJsonError struct {
type JsonAnonymizer struct {
transformerMappings []*mgmtv1alpha1.TransformerMapping
- transformerExecutors []*transformer.TransformerExecutor
+ transformerExecutors []*transformer_executor.TransformerExecutor
defaultTransformers *mgmtv1alpha1.DefaultTransformersConfig
defaultTransformerExecutor *DefaultExecutors
compiledQuery *gojq.Code
@@ -359,21 +359,21 @@ func initTransformerExecutors(
anonymizeConfig *anonymizeConfig,
transformerClient mgmtv1alpha1connect.TransformersServiceClient,
logger *slog.Logger,
-) ([]*transformer.TransformerExecutor, error) {
- executors := []*transformer.TransformerExecutor{}
- execOpts := []transformer.TransformerExecutorOption{
- transformer.WithLogger(logger),
- transformer.WithUserDefinedTransformerResolver(newUdtResolver(transformerClient)),
+) ([]*transformer_executor.TransformerExecutor, error) {
+ executors := []*transformer_executor.TransformerExecutor{}
+ execOpts := []transformer_executor.TransformerExecutorOption{
+ transformer_executor.WithLogger(logger),
+ transformer_executor.WithUserDefinedTransformerResolver(newUdtResolver(transformerClient)),
}
if anonymizeConfig != nil && anonymizeConfig.analyze != nil && anonymizeConfig.anonymize != nil {
execOpts = append(
execOpts,
- transformer.WithTransformPiiTextConfig(anonymizeConfig.analyze, anonymizeConfig.anonymize, newNeosyncOperatorApi(execOpts), anonymizeConfig.defaultLanguage),
+ transformer_executor.WithTransformPiiTextConfig(anonymizeConfig.analyze, anonymizeConfig.anonymize, newNeosyncOperatorApi(execOpts), anonymizeConfig.defaultLanguage),
)
}
for _, mapping := range transformerMappings {
- executor, err := transformer.InitializeTransformerByConfigType(mapping.GetTransformer(), execOpts...)
+ executor, err := transformer_executor.InitializeTransformerByConfigType(mapping.GetTransformer(), execOpts...)
if err != nil {
return nil, fmt.Errorf("failed to initialize transformer for expression '%s': %v", mapping.GetExpression(), err)
}
@@ -384,9 +384,9 @@ func initTransformerExecutors(
}
type DefaultExecutors struct {
- S *transformer.TransformerExecutor
- N *transformer.TransformerExecutor
- Boolean *transformer.TransformerExecutor
+ S *transformer_executor.TransformerExecutor
+ N *transformer_executor.TransformerExecutor
+ Boolean *transformer_executor.TransformerExecutor
}
func initDefaultTransformerExecutors(
@@ -395,30 +395,30 @@ func initDefaultTransformerExecutors(
transformerClient mgmtv1alpha1connect.TransformersServiceClient,
logger *slog.Logger,
) (*DefaultExecutors, error) {
- execOpts := []transformer.TransformerExecutorOption{
- transformer.WithLogger(logger),
- transformer.WithUserDefinedTransformerResolver(newUdtResolver(transformerClient)),
+ execOpts := []transformer_executor.TransformerExecutorOption{
+ transformer_executor.WithLogger(logger),
+ transformer_executor.WithUserDefinedTransformerResolver(newUdtResolver(transformerClient)),
}
if anonymizeConfig != nil && anonymizeConfig.analyze != nil && anonymizeConfig.anonymize != nil {
- execOpts = append(execOpts, transformer.WithTransformPiiTextConfig(anonymizeConfig.analyze, anonymizeConfig.anonymize, newNeosyncOperatorApi(execOpts), anonymizeConfig.defaultLanguage))
+ execOpts = append(execOpts, transformer_executor.WithTransformPiiTextConfig(anonymizeConfig.analyze, anonymizeConfig.anonymize, newNeosyncOperatorApi(execOpts), anonymizeConfig.defaultLanguage))
}
- var stringExecutor, numberExecutor, booleanExecutor *transformer.TransformerExecutor
+ var stringExecutor, numberExecutor, booleanExecutor *transformer_executor.TransformerExecutor
var err error
if defaultTransformer.S != nil {
- stringExecutor, err = transformer.InitializeTransformerByConfigType(defaultTransformer.S, execOpts...)
+ stringExecutor, err = transformer_executor.InitializeTransformerByConfigType(defaultTransformer.S, execOpts...)
if err != nil {
return nil, err
}
}
if defaultTransformer.N != nil {
- numberExecutor, err = transformer.InitializeTransformerByConfigType(defaultTransformer.N, execOpts...)
+ numberExecutor, err = transformer_executor.InitializeTransformerByConfigType(defaultTransformer.N, execOpts...)
if err != nil {
return nil, err
}
}
if defaultTransformer.Boolean != nil {
- booleanExecutor, err = transformer.InitializeTransformerByConfigType(defaultTransformer.Boolean, execOpts...)
+ booleanExecutor, err = transformer_executor.InitializeTransformerByConfigType(defaultTransformer.Boolean, execOpts...)
if err != nil {
return nil, err
}
diff --git a/internal/json-anonymizer/neosync-operator.go b/internal/json-anonymizer/neosync-operator.go
index 4dbc40bd45..7fe21d9249 100644
--- a/internal/json-anonymizer/neosync-operator.go
+++ b/internal/json-anonymizer/neosync-operator.go
@@ -7,19 +7,19 @@ import (
"connectrpc.com/connect"
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
"github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect"
- transformer "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
+ "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformer_executor"
)
type neosyncOperatorApi struct {
- opts []transformer.TransformerExecutorOption
+ opts []transformer_executor.TransformerExecutorOption
}
-func newNeosyncOperatorApi(executorOpts []transformer.TransformerExecutorOption) *neosyncOperatorApi {
+func newNeosyncOperatorApi(executorOpts []transformer_executor.TransformerExecutorOption) *neosyncOperatorApi {
return &neosyncOperatorApi{opts: executorOpts}
}
func (n *neosyncOperatorApi) Transform(ctx context.Context, config *mgmtv1alpha1.TransformerConfig, value string) (string, error) {
- executor, err := transformer.InitializeTransformerByConfigType(config, n.opts...)
+ executor, err := transformer_executor.InitializeTransformerByConfigType(config, n.opts...)
if err != nil {
return "", err
}
diff --git a/internal/json-anonymizer/neosync-operator_test.go b/internal/json-anonymizer/neosync-operator_test.go
index b9808f7c17..5c9b20ceaa 100644
--- a/internal/json-anonymizer/neosync-operator_test.go
+++ b/internal/json-anonymizer/neosync-operator_test.go
@@ -6,15 +6,16 @@ import (
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
"github.com/nucleuscloud/neosync/internal/testutil"
- "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
+ "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformer_executor"
+
"github.com/stretchr/testify/require"
)
func Test_NeosyncOperator(t *testing.T) {
t.Run("Transform", func(t *testing.T) {
t.Run("string", func(t *testing.T) {
- operator := newNeosyncOperatorApi([]transformers.TransformerExecutorOption{
- transformers.WithLogger(testutil.GetTestLogger(t)),
+ operator := newNeosyncOperatorApi([]transformer_executor.TransformerExecutorOption{
+ transformer_executor.WithLogger(testutil.GetTestLogger(t)),
})
actual, err := operator.Transform(context.Background(), &mgmtv1alpha1.TransformerConfig{
Config: &mgmtv1alpha1.TransformerConfig_GenerateFirstNameConfig{
@@ -26,8 +27,8 @@ func Test_NeosyncOperator(t *testing.T) {
require.IsType(t, "", actual)
})
t.Run("default_empty_string", func(t *testing.T) {
- operator := newNeosyncOperatorApi([]transformers.TransformerExecutorOption{
- transformers.WithLogger(testutil.GetTestLogger(t)),
+ operator := newNeosyncOperatorApi([]transformer_executor.TransformerExecutorOption{
+ transformer_executor.WithLogger(testutil.GetTestLogger(t)),
})
actual, err := operator.Transform(context.Background(), &mgmtv1alpha1.TransformerConfig{
Config: &mgmtv1alpha1.TransformerConfig_TransformFirstNameConfig{
@@ -39,8 +40,8 @@ func Test_NeosyncOperator(t *testing.T) {
require.IsType(t, "", actual)
})
t.Run("default_number", func(t *testing.T) {
- operator := newNeosyncOperatorApi([]transformers.TransformerExecutorOption{
- transformers.WithLogger(testutil.GetTestLogger(t)),
+ operator := newNeosyncOperatorApi([]transformer_executor.TransformerExecutorOption{
+ transformer_executor.WithLogger(testutil.GetTestLogger(t)),
})
actual, err := operator.Transform(context.Background(), &mgmtv1alpha1.TransformerConfig{
Config: &mgmtv1alpha1.TransformerConfig_GenerateCardNumberConfig{
diff --git a/python/src/neosync/mgmt/v1alpha1/job_pb2.py b/python/src/neosync/mgmt/v1alpha1/job_pb2.py
index 6e9223690c..6c9de66979 100644
--- a/python/src/neosync/mgmt/v1alpha1/job_pb2.py
+++ b/python/src/neosync/mgmt/v1alpha1/job_pb2.py
@@ -27,7 +27,7 @@
from mgmt.v1alpha1 import transformer_pb2 as mgmt_dot_v1alpha1_dot_transformer__pb2
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17mgmt/v1alpha1/job.proto\x12\rmgmt.v1alpha1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1fmgmt/v1alpha1/transformer.proto\"9\n\x0eGetJobsRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"9\n\x0fGetJobsResponse\x12&\n\x04jobs\x18\x01 \x03(\x0b\x32\x12.mgmt.v1alpha1.JobR\x04jobs\"N\n\tJobSource\x12\x41\n\x07options\x18\x01 \x01(\x0b\x32\x1f.mgmt.v1alpha1.JobSourceOptionsB\x06\xbaH\x03\xc8\x01\x01R\x07options\"\xe9\x04\n\x10JobSourceOptions\x12L\n\x08postgres\x18\x01 \x01(\x0b\x32..mgmt.v1alpha1.PostgresSourceConnectionOptionsH\x00R\x08postgres\x12\x44\n\x06\x61ws_s3\x18\x02 \x01(\x0b\x32+.mgmt.v1alpha1.AwsS3SourceConnectionOptionsH\x00R\x05\x61wsS3\x12\x43\n\x05mysql\x18\x03 \x01(\x0b\x32+.mgmt.v1alpha1.MysqlSourceConnectionOptionsH\x00R\x05mysql\x12\x42\n\x08generate\x18\x04 \x01(\x0b\x32$.mgmt.v1alpha1.GenerateSourceOptionsH\x00R\x08generate\x12I\n\x0b\x61i_generate\x18\x05 \x01(\x0b\x32&.mgmt.v1alpha1.AiGenerateSourceOptionsH\x00R\naiGenerate\x12I\n\x07mongodb\x18\x06 \x01(\x0b\x32-.mgmt.v1alpha1.MongoDBSourceConnectionOptionsH\x00R\x07mongodb\x12L\n\x08\x64ynamodb\x18\x07 \x01(\x0b\x32..mgmt.v1alpha1.DynamoDBSourceConnectionOptionsH\x00R\x08\x64ynamodb\x12\x43\n\x05mssql\x18\x08 \x01(\x0b\x32+.mgmt.v1alpha1.MssqlSourceConnectionOptionsH\x00R\x05mssqlB\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01\"\x85\x01\n\x14\x43reateJobDestination\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12>\n\x07options\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.JobDestinationOptionsR\x07options\"\x8f\x01\n\x0eJobDestination\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12>\n\x07options\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.JobDestinationOptionsR\x07options\x12\x0e\n\x02id\x18\x03 \x01(\tR\x02id\"\xb6\x03\n\x17\x41iGenerateSourceOptions\x12\x32\n\x10\x61i_connection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0e\x61iConnectionId\x12O\n\x07schemas\x18\x02 \x03(\x0b\x32+.mgmt.v1alpha1.AiGenerateSourceSchemaOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x07schemas\x12\x44\n\x17\x66k_source_connection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\x14\x66kSourceConnectionId\x88\x01\x01\x12&\n\nmodel_name\x18\x04 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\tmodelName\x12$\n\x0buser_prompt\x18\x05 \x01(\tH\x01R\nuserPrompt\x88\x01\x01\x12>\n\x13generate_batch_size\x18\x06 \x01(\x03\x42\t\xbaH\x06\"\x04\x18\x64(\x01H\x02R\x11generateBatchSize\x88\x01\x01\x42\x1a\n\x18_fk_source_connection_idB\x0e\n\x0c_user_promptB\x16\n\x14_generate_batch_size\"\x8d\x01\n\x1c\x41iGenerateSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12L\n\x06tables\x18\x02 \x03(\x0b\x32*.mgmt.v1alpha1.AiGenerateSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"e\n\x1b\x41iGenerateSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12\'\n\trow_count\x18\x02 \x01(\x03\x42\n\xbaH\x07\"\x05\x18\xe8\x07(\x01R\x08rowCount\"\xce\x01\n\x15GenerateSourceOptions\x12M\n\x07schemas\x18\x01 \x03(\x0b\x32).mgmt.v1alpha1.GenerateSourceSchemaOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x07schemas\x12\x44\n\x17\x66k_source_connection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\x14\x66kSourceConnectionId\x88\x01\x01\x42\x1a\n\x18_fk_source_connection_idJ\x04\x08\x02\x10\x03\"\x89\x01\n\x1aGenerateSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12J\n\x06tables\x18\x02 \x03(\x0b\x32(.mgmt.v1alpha1.GenerateSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"`\n\x19GenerateSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12$\n\trow_count\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01R\x08rowCount\"O\n\x1eMongoDBSourceConnectionOptions\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\"\xaf\x02\n\x1f\x44ynamoDBSourceConnectionOptions\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12@\n\x06tables\x18\x02 \x03(\x0b\x32(.mgmt.v1alpha1.DynamoDBSourceTableOptionR\x06tables\x12\x65\n\x13unmapped_transforms\x18\x03 \x01(\x0b\x32\x34.mgmt.v1alpha1.DynamoDBSourceUnmappedTransformConfigR\x12unmappedTransforms\x12\x34\n\x16\x65nable_consistent_read\x18\x04 \x01(\x08R\x14\x65nableConsistentRead\"\x8f\x02\n%DynamoDBSourceUnmappedTransformConfig\x12\x32\n\x01\x62\x18\x01 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x01\x62\x12>\n\x07\x62oolean\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x07\x62oolean\x12\x32\n\x01n\x18\x04 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x01n\x12\x32\n\x01s\x18\x06 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x01sJ\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06\"s\n\x19\x44ynamoDBSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"\xaf\x08\n\x1fPostgresSourceConnectionOptions\x12\x43\n\x07schemas\x18\x02 \x03(\x0b\x32).mgmt.v1alpha1.PostgresSourceSchemaOptionR\x07schemas\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12H\n!subset_by_foreign_key_constraints\x18\x04 \x01(\x08R\x1dsubsetByForeignKeyConstraints\x12\x89\x01\n\x1cnew_column_addition_strategy\x18\x05 \x01(\x0b\x32H.mgmt.v1alpha1.PostgresSourceConnectionOptions.NewColumnAdditionStrategyR\x19newColumnAdditionStrategy\x12|\n\x17\x63olumn_removal_strategy\x18\x06 \x01(\x0b\x32\x44.mgmt.v1alpha1.PostgresSourceConnectionOptions.ColumnRemovalStrategyR\x15\x63olumnRemovalStrategy\x1a\x9b\x02\n\x19NewColumnAdditionStrategy\x12m\n\x08halt_job\x18\x01 \x01(\x0b\x32P.mgmt.v1alpha1.PostgresSourceConnectionOptions.NewColumnAdditionStrategy.HaltJobH\x00R\x07haltJob\x12m\n\x08\x61uto_map\x18\x02 \x01(\x0b\x32P.mgmt.v1alpha1.PostgresSourceConnectionOptions.NewColumnAdditionStrategy.AutoMapH\x00R\x07\x61utoMap\x1a\t\n\x07HaltJob\x1a\t\n\x07\x41utoMapB\n\n\x08strategy\x1a\x9f\x02\n\x15\x43olumnRemovalStrategy\x12i\n\x08halt_job\x18\x01 \x01(\x0b\x32L.mgmt.v1alpha1.PostgresSourceConnectionOptions.ColumnRemovalStrategy.HaltJobH\x00R\x07haltJob\x12u\n\x0c\x63ontinue_job\x18\x02 \x01(\x0b\x32P.mgmt.v1alpha1.PostgresSourceConnectionOptions.ColumnRemovalStrategy.ContinueJobH\x00R\x0b\x63ontinueJob\x1a\t\n\x07HaltJob\x1a\r\n\x0b\x43ontinueJobB\n\n\x08strategyJ\x04\x08\x01\x10\x02\"\x89\x01\n\x1aPostgresSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12J\n\x06tables\x18\x02 \x03(\x0b\x32(.mgmt.v1alpha1.PostgresSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"s\n\x19PostgresSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"\xae\x05\n\x1cMysqlSourceConnectionOptions\x12<\n\x1bhalt_on_new_column_addition\x18\x01 \x01(\x08R\x17haltOnNewColumnAddition\x12@\n\x07schemas\x18\x02 \x03(\x0b\x32&.mgmt.v1alpha1.MysqlSourceSchemaOptionR\x07schemas\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12H\n!subset_by_foreign_key_constraints\x18\x04 \x01(\x08R\x1dsubsetByForeignKeyConstraints\x12y\n\x17\x63olumn_removal_strategy\x18\x05 \x01(\x0b\x32\x41.mgmt.v1alpha1.MysqlSourceConnectionOptions.ColumnRemovalStrategyR\x15\x63olumnRemovalStrategy\x1a\x99\x02\n\x15\x43olumnRemovalStrategy\x12\x66\n\x08halt_job\x18\x01 \x01(\x0b\x32I.mgmt.v1alpha1.MysqlSourceConnectionOptions.ColumnRemovalStrategy.HaltJobH\x00R\x07haltJob\x12r\n\x0c\x63ontinue_job\x18\x02 \x01(\x0b\x32M.mgmt.v1alpha1.MysqlSourceConnectionOptions.ColumnRemovalStrategy.ContinueJobH\x00R\x0b\x63ontinueJob\x1a\t\n\x07HaltJob\x1a\r\n\x0b\x43ontinueJobB\n\n\x08strategy\"\x83\x01\n\x17MysqlSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12G\n\x06tables\x18\x02 \x03(\x0b\x32%.mgmt.v1alpha1.MysqlSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"p\n\x16MysqlSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"\xae\x05\n\x1cMssqlSourceConnectionOptions\x12<\n\x1bhalt_on_new_column_addition\x18\x01 \x01(\x08R\x17haltOnNewColumnAddition\x12@\n\x07schemas\x18\x02 \x03(\x0b\x32&.mgmt.v1alpha1.MssqlSourceSchemaOptionR\x07schemas\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12H\n!subset_by_foreign_key_constraints\x18\x04 \x01(\x08R\x1dsubsetByForeignKeyConstraints\x12y\n\x17\x63olumn_removal_strategy\x18\x05 \x01(\x0b\x32\x41.mgmt.v1alpha1.MssqlSourceConnectionOptions.ColumnRemovalStrategyR\x15\x63olumnRemovalStrategy\x1a\x99\x02\n\x15\x43olumnRemovalStrategy\x12\x66\n\x08halt_job\x18\x01 \x01(\x0b\x32I.mgmt.v1alpha1.MssqlSourceConnectionOptions.ColumnRemovalStrategy.HaltJobH\x00R\x07haltJob\x12r\n\x0c\x63ontinue_job\x18\x02 \x01(\x0b\x32M.mgmt.v1alpha1.MssqlSourceConnectionOptions.ColumnRemovalStrategy.ContinueJobH\x00R\x0b\x63ontinueJob\x1a\t\n\x07HaltJob\x1a\r\n\x0b\x43ontinueJobB\n\n\x08strategy\"\x83\x01\n\x17MssqlSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12G\n\x06tables\x18\x02 \x03(\x0b\x32%.mgmt.v1alpha1.MssqlSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"p\n\x16MssqlSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"M\n\x1c\x41wsS3SourceConnectionOptions\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\"\xcf\x05\n\x15JobDestinationOptions\x12`\n\x10postgres_options\x18\x01 \x01(\x0b\x32\x33.mgmt.v1alpha1.PostgresDestinationConnectionOptionsH\x00R\x0fpostgresOptions\x12X\n\x0e\x61ws_s3_options\x18\x02 \x01(\x0b\x32\x30.mgmt.v1alpha1.AwsS3DestinationConnectionOptionsH\x00R\x0c\x61wsS3Options\x12W\n\rmysql_options\x18\x03 \x01(\x0b\x32\x30.mgmt.v1alpha1.MysqlDestinationConnectionOptionsH\x00R\x0cmysqlOptions\x12]\n\x0fmongodb_options\x18\x04 \x01(\x0b\x32\x32.mgmt.v1alpha1.MongoDBDestinationConnectionOptionsH\x00R\x0emongodbOptions\x12v\n\x18gcp_cloudstorage_options\x18\x05 \x01(\x0b\x32:.mgmt.v1alpha1.GcpCloudStorageDestinationConnectionOptionsH\x00R\x16gcpCloudstorageOptions\x12`\n\x10\x64ynamodb_options\x18\x06 \x01(\x0b\x32\x33.mgmt.v1alpha1.DynamoDBDestinationConnectionOptionsH\x00R\x0f\x64ynamodbOptions\x12W\n\rmssql_options\x18\x07 \x01(\x0b\x32\x30.mgmt.v1alpha1.MssqlDestinationConnectionOptionsH\x00R\x0cmssqlOptionsB\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01\"%\n#MongoDBDestinationConnectionOptions\"-\n+GcpCloudStorageDestinationConnectionOptions\"}\n$DynamoDBDestinationConnectionOptions\x12U\n\x0etable_mappings\x18\x01 \x03(\x0b\x32..mgmt.v1alpha1.DynamoDBDestinationTableMappingR\rtableMappings\"q\n\x1f\x44ynamoDBDestinationTableMapping\x12!\n\x0csource_table\x18\x01 \x01(\tR\x0bsourceTable\x12+\n\x11\x64\x65stination_table\x18\x02 \x01(\tR\x10\x64\x65stinationTable\"\xa4\x03\n$PostgresDestinationConnectionOptions\x12Q\n\x0etruncate_table\x18\x01 \x01(\x0b\x32*.mgmt.v1alpha1.PostgresTruncateTableConfigR\rtruncateTable\x12*\n\x11init_table_schema\x18\x02 \x01(\x08R\x0finitTableSchema\x12H\n\x0bon_conflict\x18\x03 \x01(\x0b\x32\'.mgmt.v1alpha1.PostgresOnConflictConfigR\nonConflict\x12=\n\x1bskip_foreign_key_violations\x18\x04 \x01(\x08R\x18skipForeignKeyViolations\x12\x30\n\x05\x62\x61tch\x18\x05 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\x12\x30\n\rmax_in_flight\x18\x06 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x42\x10\n\x0e_max_in_flight\"\xc4\x02\n\x18PostgresOnConflictConfig\x12\x1d\n\ndo_nothing\x18\x01 \x01(\x08R\tdoNothing\x12_\n\x07nothing\x18\x02 \x01(\x0b\x32\x43.mgmt.v1alpha1.PostgresOnConflictConfig.PostgresOnConflictDoNothingH\x00R\x07nothing\x12Z\n\x06update\x18\x03 \x01(\x0b\x32@.mgmt.v1alpha1.PostgresOnConflictConfig.PostgresOnConflictUpdateH\x00R\x06update\x1a\x1d\n\x1bPostgresOnConflictDoNothing\x1a\x1a\n\x18PostgresOnConflictUpdateB\x11\n\x08strategy\x12\x05\xbaH\x02\x08\x00\"m\n\x1bPostgresTruncateTableConfig\x12\x34\n\x16truncate_before_insert\x18\x01 \x01(\x08R\x14truncateBeforeInsert\x12\x18\n\x07\x63\x61scade\x18\x02 \x01(\x08R\x07\x63\x61scade\"\x9b\x03\n!MysqlDestinationConnectionOptions\x12N\n\x0etruncate_table\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.MysqlTruncateTableConfigR\rtruncateTable\x12*\n\x11init_table_schema\x18\x02 \x01(\x08R\x0finitTableSchema\x12\x45\n\x0bon_conflict\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.MysqlOnConflictConfigR\nonConflict\x12=\n\x1bskip_foreign_key_violations\x18\x04 \x01(\x08R\x18skipForeignKeyViolations\x12\x30\n\x05\x62\x61tch\x18\x05 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\x12\x30\n\rmax_in_flight\x18\x06 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x42\x10\n\x0e_max_in_flight\"P\n\x18MysqlTruncateTableConfig\x12\x34\n\x16truncate_before_insert\x18\x01 \x01(\x08R\x14truncateBeforeInsert\"\xaf\x02\n\x15MysqlOnConflictConfig\x12\x1d\n\ndo_nothing\x18\x01 \x01(\x08R\tdoNothing\x12Y\n\x07nothing\x18\x02 \x01(\x0b\x32=.mgmt.v1alpha1.MysqlOnConflictConfig.MysqlOnConflictDoNothingH\x00R\x07nothing\x12T\n\x06update\x18\x03 \x01(\x0b\x32:.mgmt.v1alpha1.MysqlOnConflictConfig.MysqlOnConflictUpdateH\x00R\x06update\x1a\x1a\n\x18MysqlOnConflictDoNothing\x1a\x17\n\x15MysqlOnConflictUpdateB\x11\n\x08strategy\x12\x05\xbaH\x02\x08\x00\"\x9b\x03\n!MssqlDestinationConnectionOptions\x12N\n\x0etruncate_table\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.MssqlTruncateTableConfigR\rtruncateTable\x12*\n\x11init_table_schema\x18\x02 \x01(\x08R\x0finitTableSchema\x12\x45\n\x0bon_conflict\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.MssqlOnConflictConfigR\nonConflict\x12=\n\x1bskip_foreign_key_violations\x18\x04 \x01(\x08R\x18skipForeignKeyViolations\x12\x30\n\x05\x62\x61tch\x18\x05 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\x12\x30\n\rmax_in_flight\x18\x06 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x42\x10\n\x0e_max_in_flight\"P\n\x18MssqlTruncateTableConfig\x12\x34\n\x16truncate_before_insert\x18\x01 \x01(\x08R\x14truncateBeforeInsert\"6\n\x15MssqlOnConflictConfig\x12\x1d\n\ndo_nothing\x18\x01 \x01(\x08R\tdoNothing\"\xb9\x04\n!AwsS3DestinationConnectionOptions\x12\x62\n\rstorage_class\x18\x01 \x01(\x0e\x32=.mgmt.v1alpha1.AwsS3DestinationConnectionOptions.StorageClassR\x0cstorageClass\x12\x30\n\rmax_in_flight\x18\x02 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x12\x1d\n\x07timeout\x18\x03 \x01(\tH\x01R\x07timeout\x88\x01\x01\x12\x30\n\x05\x62\x61tch\x18\x04 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\"\x8e\x02\n\x0cStorageClass\x12\x1d\n\x19STORAGE_CLASS_UNSPECIFIED\x10\x00\x12\x1a\n\x16STORAGE_CLASS_STANDARD\x10\x01\x12$\n STORAGE_CLASS_REDUCED_REDUNDANCY\x10\x02\x12\x19\n\x15STORAGE_CLASS_GLACIER\x10\x03\x12\x1d\n\x19STORAGE_CLASS_STANDARD_IA\x10\x04\x12\x1c\n\x18STORAGE_CLASS_ONEZONE_IA\x10\x05\x12%\n!STORAGE_CLASS_INTELLIGENT_TIERING\x10\x06\x12\x1e\n\x1aSTORAGE_CLASS_DEEP_ARCHIVE\x10\x07\x42\x10\n\x0e_max_in_flightB\n\n\x08_timeout\"Z\n\x0b\x42\x61tchConfig\x12\x19\n\x05\x63ount\x18\x01 \x01(\rH\x00R\x05\x63ount\x88\x01\x01\x12\x1b\n\x06period\x18\x02 \x01(\tH\x01R\x06period\x88\x01\x01\x42\x08\n\x06_countB\t\n\x07_period\"\xf2\x04\n\x10\x43reateJobRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x34\n\x08job_name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x07jobName\x12(\n\rcron_schedule\x18\x03 \x01(\tH\x00R\x0c\x63ronSchedule\x88\x01\x01\x12\x35\n\x08mappings\x18\x04 \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12\x30\n\x06source\x18\x05 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceR\x06source\x12G\n\x0c\x64\x65stinations\x18\x06 \x03(\x0b\x32#.mgmt.v1alpha1.CreateJobDestinationR\x0c\x64\x65stinations\x12(\n\x10initiate_job_run\x18\x07 \x01(\x08R\x0einitiateJobRun\x12I\n\x10workflow_options\x18\x08 \x01(\x0b\x32\x1e.mgmt.v1alpha1.WorkflowOptionsR\x0fworkflowOptions\x12\x41\n\x0csync_options\x18\t \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityOptionsR\x0bsyncOptions\x12Y\n\x14virtual_foreign_keys\x18\n \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeysB\x10\n\x0e_cron_schedule\"q\n\x0fWorkflowOptions\x12$\n\x0brun_timeout\x18\x08 \x01(\x03H\x00R\nrunTimeout\x88\x01\x01\x42\x0e\n\x0c_run_timeoutJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x05\x10\x06J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08\"\x95\x02\n\x0f\x41\x63tivityOptions\x12G\n\x19schedule_to_close_timeout\x18\x01 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x16scheduleToCloseTimeout\x88\x01\x01\x12\x41\n\x16start_to_close_timeout\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x01R\x13startToCloseTimeout\x88\x01\x01\x12=\n\x0cretry_policy\x18\x03 \x01(\x0b\x32\x1a.mgmt.v1alpha1.RetryPolicyR\x0bretryPolicyB\x1c\n\x1a_schedule_to_close_timeoutB\x19\n\x17_start_to_close_timeout\"[\n\x0bRetryPolicy\x12\x37\n\x10maximum_attempts\x18\x01 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00H\x00R\x0fmaximumAttempts\x88\x01\x01\x42\x13\n\x11_maximum_attempts\"9\n\x11\x43reateJobResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"W\n\x15JobMappingTransformer\x12\x38\n\x06\x63onfig\x18\x03 \x01(\x0b\x32 .mgmt.v1alpha1.TransformerConfigR\x06\x63onfigJ\x04\x08\x01\x10\x02\"\xb5\x01\n\nJobMapping\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12\x1d\n\x05table\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12\x1f\n\x06\x63olumn\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06\x63olumn\x12\x46\n\x0btransformer\x18\x05 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x0btransformer\")\n\rGetJobRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"6\n\x0eGetJobResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"p\n\x18UpdateJobScheduleRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12(\n\rcron_schedule\x18\x02 \x01(\tH\x00R\x0c\x63ronSchedule\x88\x01\x01\x42\x10\n\x0e_cron_schedule\"A\n\x19UpdateJobScheduleResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"c\n\x0fPauseJobRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x14\n\x05pause\x18\x02 \x01(\x08R\x05pause\x12\x17\n\x04note\x18\x03 \x01(\tH\x00R\x04note\x88\x01\x01\x42\x07\n\x05_note\"8\n\x10PauseJobResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"\x80\x02\n UpdateJobSourceConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x30\n\x06source\x18\x02 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceR\x06source\x12\x35\n\x08mappings\x18\x03 \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12Y\n\x14virtual_foreign_keys\x18\x04 \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeys\"I\n!UpdateJobSourceConnectionResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"r\n\x1aPostgresSourceSchemaSubset\x12T\n\x10postgres_schemas\x18\x01 \x03(\x0b\x32).mgmt.v1alpha1.PostgresSourceSchemaOptionR\x0fpostgresSchemas\"f\n\x17MysqlSourceSchemaSubset\x12K\n\rmysql_schemas\x18\x01 \x03(\x0b\x32&.mgmt.v1alpha1.MysqlSourceSchemaOptionR\x0cmysqlSchemas\"^\n\x1a\x44ynamoDBSourceSchemaSubset\x12@\n\x06tables\x18\x01 \x03(\x0b\x32(.mgmt.v1alpha1.DynamoDBSourceTableOptionR\x06tables\"f\n\x17MssqlSourceSchemaSubset\x12K\n\rmssql_schemas\x18\x01 \x03(\x0b\x32&.mgmt.v1alpha1.MssqlSourceSchemaOptionR\x0cmssqlSchemas\"\xf8\x02\n\x18JobSourceSqlSubetSchemas\x12T\n\x0fpostgres_subset\x18\x02 \x01(\x0b\x32).mgmt.v1alpha1.PostgresSourceSchemaSubsetH\x00R\x0epostgresSubset\x12K\n\x0cmysql_subset\x18\x03 \x01(\x0b\x32&.mgmt.v1alpha1.MysqlSourceSchemaSubsetH\x00R\x0bmysqlSubset\x12T\n\x0f\x64ynamodb_subset\x18\x04 \x01(\x0b\x32).mgmt.v1alpha1.DynamoDBSourceSchemaSubsetH\x00R\x0e\x64ynamodbSubset\x12K\n\x0cmssql_subset\x18\x05 \x01(\x0b\x32&.mgmt.v1alpha1.MssqlSourceSchemaSubsetH\x00R\x0bmssqlSubsetB\x10\n\x07schemas\x12\x05\xbaH\x02\x08\x01J\x04\x08\x01\x10\x02\"\xd0\x01\n\'SetJobSourceSqlConnectionSubsetsRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x41\n\x07schemas\x18\x02 \x01(\x0b\x32\'.mgmt.v1alpha1.JobSourceSqlSubetSchemasR\x07schemas\x12H\n!subset_by_foreign_key_constraints\x18\x03 \x01(\x08R\x1dsubsetByForeignKeyConstraints\"P\n(SetJobSourceSqlConnectionSubsetsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"\xde\x01\n%UpdateJobDestinationConnectionRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12-\n\rconnection_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12>\n\x07options\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.JobDestinationOptionsR\x07options\x12%\n\x0e\x64\x65stination_id\x18\x04 \x01(\tR\rdestinationId\"N\n&UpdateJobDestinationConnectionResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"X\n%DeleteJobDestinationConnectionRequest\x12/\n\x0e\x64\x65stination_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\rdestinationId\"(\n&DeleteJobDestinationConnectionResponse\"\x92\x01\n&CreateJobDestinationConnectionsRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12G\n\x0c\x64\x65stinations\x18\x02 \x03(\x0b\x32#.mgmt.v1alpha1.CreateJobDestinationR\x0c\x64\x65stinations\"O\n\'CreateJobDestinationConnectionsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\",\n\x10\x44\x65leteJobRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\x13\n\x11\x44\x65leteJobResponse\"s\n\x19IsJobNameAvailableRequest\x12-\n\x04name\x18\x01 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"?\n\x1aIsJobNameAvailableResponse\x12!\n\x0cis_available\x18\x01 \x01(\x08R\x0bisAvailable\"g\n\x11GetJobRunsRequest\x12!\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\x05jobId\x12)\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\taccountIdB\x04\n\x02id\"F\n\x12GetJobRunsResponse\x12\x30\n\x08job_runs\x18\x01 \x03(\x0b\x32\x15.mgmt.v1alpha1.JobRunR\x07jobRuns\"Y\n\x10GetJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"C\n\x11GetJobRunResponse\x12.\n\x07job_run\x18\x01 \x01(\x0b\x32\x15.mgmt.v1alpha1.JobRunR\x06jobRun\"6\n\x13\x43reateJobRunRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"\x16\n\x14\x43reateJobRunResponse\"\\\n\x13\x43\x61ncelJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"\x16\n\x14\x43\x61ncelJobRunResponse\"\xe9\x05\n\x03Job\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12+\n\x12\x63reated_by_user_id\x18\x02 \x01(\tR\x0f\x63reatedByUserId\x12\x39\n\ncreated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n\x12updated_by_user_id\x18\x04 \x01(\tR\x0fupdatedByUserId\x12\x39\n\nupdated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x12\n\x04name\x18\x06 \x01(\tR\x04name\x12\x30\n\x06source\x18\x07 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceR\x06source\x12\x41\n\x0c\x64\x65stinations\x18\x08 \x03(\x0b\x32\x1d.mgmt.v1alpha1.JobDestinationR\x0c\x64\x65stinations\x12\x35\n\x08mappings\x18\t \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12(\n\rcron_schedule\x18\n \x01(\tH\x00R\x0c\x63ronSchedule\x88\x01\x01\x12\x1d\n\naccount_id\x18\x0b \x01(\tR\taccountId\x12\x41\n\x0csync_options\x18\x0c \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityOptionsR\x0bsyncOptions\x12I\n\x10workflow_options\x18\r \x01(\x0b\x32\x1e.mgmt.v1alpha1.WorkflowOptionsR\x0fworkflowOptions\x12Y\n\x14virtual_foreign_keys\x18\x0e \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeysB\x10\n\x0e_cron_schedule\"g\n\x0cJobRecentRun\x12\x39\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12\x1c\n\njob_run_id\x18\x02 \x01(\tR\x08jobRunId\":\n\x17GetJobRecentRunsRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"X\n\x18GetJobRecentRunsResponse\x12<\n\x0brecent_runs\x18\x01 \x03(\x0b\x32\x1b.mgmt.v1alpha1.JobRecentRunR\nrecentRuns\"O\n\x0bJobNextRuns\x12@\n\x0enext_run_times\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.TimestampR\x0cnextRunTimes\"8\n\x15GetJobNextRunsRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"Q\n\x16GetJobNextRunsResponse\x12\x37\n\tnext_runs\x18\x01 \x01(\x0b\x32\x1a.mgmt.v1alpha1.JobNextRunsR\x08nextRuns\"6\n\x13GetJobStatusRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"H\n\x14GetJobStatusResponse\x12\x30\n\x06status\x18\x01 \x01(\x0e\x32\x18.mgmt.v1alpha1.JobStatusR\x06status\"d\n\x0fJobStatusRecord\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12\x30\n\x06status\x18\x02 \x01(\x0e\x32\x18.mgmt.v1alpha1.JobStatusR\x06status\"@\n\x15GetJobStatusesRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"T\n\x16GetJobStatusesResponse\x12:\n\x08statuses\x18\x01 \x03(\x0b\x32\x1e.mgmt.v1alpha1.JobStatusRecordR\x08statuses\"+\n\x0f\x41\x63tivityFailure\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\"\xc6\x01\n\x0fPendingActivity\x12\x35\n\x06status\x18\x01 \x01(\x0e\x32\x1d.mgmt.v1alpha1.ActivityStatusR\x06status\x12#\n\ractivity_name\x18\x02 \x01(\tR\x0c\x61\x63tivityName\x12\x46\n\x0clast_failure\x18\x03 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityFailureH\x00R\x0blastFailure\x88\x01\x01\x42\x0f\n\r_last_failure\"\xdd\x02\n\x06JobRun\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12\x33\n\x06status\x18\x04 \x01(\x0e\x32\x1b.mgmt.v1alpha1.JobRunStatusR\x06status\x12\x39\n\nstarted_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartedAt\x12\x42\n\x0c\x63ompleted_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\x0b\x63ompletedAt\x88\x01\x01\x12M\n\x12pending_activities\x18\x08 \x03(\x0b\x32\x1e.mgmt.v1alpha1.PendingActivityR\x11pendingActivitiesB\x0f\n\r_completed_atJ\x04\x08\x05\x10\x06\"Q\n\x14JobRunEventTaskError\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\x12\x1f\n\x0bretry_state\x18\x02 \x01(\tR\nretryState\"\xab\x01\n\x0fJobRunEventTask\x12\x0e\n\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n\x04type\x18\x02 \x01(\tR\x04type\x12\x39\n\nevent_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\teventTime\x12\x39\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.mgmt.v1alpha1.JobRunEventTaskErrorR\x05\x65rror\"B\n\x12JobRunSyncMetadata\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\"r\n\x13JobRunEventMetadata\x12H\n\rsync_metadata\x18\x01 \x01(\x0b\x32!.mgmt.v1alpha1.JobRunSyncMetadataH\x00R\x0csyncMetadataB\x11\n\x08metadata\x12\x05\xbaH\x02\x08\x01\"\x9d\x02\n\x0bJobRunEvent\x12\x0e\n\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n\x04type\x18\x02 \x01(\tR\x04type\x12\x39\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12\x39\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcloseTime\x12>\n\x08metadata\x18\x05 \x01(\x0b\x32\".mgmt.v1alpha1.JobRunEventMetadataR\x08metadata\x12\x34\n\x05tasks\x18\x06 \x03(\x0b\x32\x1e.mgmt.v1alpha1.JobRunEventTaskR\x05tasks\"_\n\x16GetJobRunEventsRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"u\n\x17GetJobRunEventsResponse\x12\x32\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1a.mgmt.v1alpha1.JobRunEventR\x06\x65vents\x12&\n\x0fis_run_complete\x18\x02 \x01(\x08R\risRunComplete\"\\\n\x13\x44\x65leteJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"\x16\n\x14\x44\x65leteJobRunResponse\"_\n\x16TerminateJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"\x19\n\x17TerminateJobRunResponse\"\xb2\x02\n\x1aGetJobRunLogsStreamRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x30\n\x06window\x18\x03 \x01(\x0e\x32\x18.mgmt.v1alpha1.LogWindowR\x06window\x12\x1f\n\x0bshould_tail\x18\x04 \x01(\x08R\nshouldTail\x12\x30\n\rmax_log_lines\x18\x05 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x0bmaxLogLines\x88\x01\x01\x12\x36\n\nlog_levels\x18\x06 \x03(\x0e\x32\x17.mgmt.v1alpha1.LogLevelR\tlogLevelsB\x10\n\x0e_max_log_lines\"\x85\x01\n\x1bGetJobRunLogsStreamResponse\x12\x19\n\x08log_line\x18\x01 \x01(\tR\x07logLine\x12=\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\ttimestamp\x88\x01\x01\x42\x0c\n\n_timestamp\"\x83\x01\n\x1cSetJobWorkflowOptionsRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12I\n\x10worfklow_options\x18\x02 \x01(\x0b\x32\x1e.mgmt.v1alpha1.WorkflowOptionsR\x0fworfklowOptions\"E\n\x1dSetJobWorkflowOptionsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"w\n\x18SetJobSyncOptionsRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x41\n\x0csync_options\x18\x02 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityOptionsR\x0bsyncOptions\"A\n\x19SetJobSyncOptionsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"\xd3\x02\n\x1aValidateJobMappingsRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x35\n\x08mappings\x18\x02 \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12Y\n\x14virtual_foreign_keys\x18\x04 \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeys\x12<\n\njob_source\x18\x05 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceH\x00R\tjobSource\x88\x01\x01\x42\r\n\x0b_job_source\"k\n\x0b\x43olumnError\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x16\n\x06\x63olumn\x18\x03 \x01(\tR\x06\x63olumn\x12\x16\n\x06\x65rrors\x18\x04 \x03(\tR\x06\x65rrors\"q\n\rColumnWarning\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x16\n\x06\x63olumn\x18\x03 \x01(\tR\x06\x63olumn\x12\x1a\n\x08warnings\x18\x05 \x03(\tR\x08warnings\"\'\n\rDatabaseError\x12\x16\n\x06\x65rrors\x18\x01 \x03(\tR\x06\x65rrors\"\xec\x01\n\x1bValidateJobMappingsResponse\x12?\n\rcolumn_errors\x18\x01 \x03(\x0b\x32\x1a.mgmt.v1alpha1.ColumnErrorR\x0c\x63olumnErrors\x12\x45\n\x0f\x64\x61tabase_errors\x18\x02 \x01(\x0b\x32\x1c.mgmt.v1alpha1.DatabaseErrorR\x0e\x64\x61tabaseErrors\x12\x45\n\x0f\x63olumn_warnings\x18\x03 \x03(\x0b\x32\x1c.mgmt.v1alpha1.ColumnWarningR\x0e\x63olumnWarnings\"[\n\x11VirtualForeignKey\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x18\n\x07\x63olumns\x18\x03 \x03(\tR\x07\x63olumns\"\xa5\x01\n\x18VirtualForeignConstraint\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x18\n\x07\x63olumns\x18\x03 \x03(\tR\x07\x63olumns\x12\x41\n\x0b\x66oreign_key\x18\x04 \x01(\x0b\x32 .mgmt.v1alpha1.VirtualForeignKeyR\nforeignKey\"\x88\x01\n\rRunContextKey\x12%\n\njob_run_id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08jobRunId\x12(\n\x0b\x65xternal_id\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\nexternalId\x12&\n\naccount_id\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\taccountId\"D\n\x14GetRunContextRequest\x12,\n\x02id\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.RunContextKeyR\x02id\"-\n\x15GetRunContextResponse\x12\x14\n\x05value\x18\x01 \x01(\x0cR\x05value\"Z\n\x14SetRunContextRequest\x12,\n\x02id\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.RunContextKeyR\x02id\x12\x14\n\x05value\x18\x02 \x01(\x0cR\x05value\"\x17\n\x15SetRunContextResponse\"[\n\x15SetRunContextsRequest\x12,\n\x02id\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.RunContextKeyR\x02id\x12\x14\n\x05value\x18\x02 \x01(\x0cR\x05value\"\x18\n\x16SetRunContextsResponse\"\xad\x03\n\x07JobHook\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12\x15\n\x06job_id\x18\x04 \x01(\tR\x05jobId\x12\x34\n\x06\x63onfig\x18\x05 \x01(\x0b\x32\x1c.mgmt.v1alpha1.JobHookConfigR\x06\x63onfig\x12+\n\x12\x63reated_by_user_id\x18\x06 \x01(\tR\x0f\x63reatedByUserId\x12\x39\n\ncreated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n\x12updated_by_user_id\x18\x08 \x01(\tR\x0fupdatedByUserId\x12\x39\n\nupdated_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x18\n\x07\x65nabled\x18\n \x01(\x08R\x07\x65nabled\x12%\n\x08priority\x18\x0b \x01(\rB\t\xbaH\x06*\x04\x18\x64(\x00R\x08priority\"\xdd\x01\n\nNewJobHook\x12-\n\x04name\x18\x01 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12)\n\x0b\x64\x65scription\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0b\x64\x65scription\x12\x34\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x1c.mgmt.v1alpha1.JobHookConfigR\x06\x63onfig\x12\x18\n\x07\x65nabled\x18\x04 \x01(\x08R\x07\x65nabled\x12%\n\x08priority\x18\x05 \x01(\rB\t\xbaH\x06*\x04\x18\x64(\x00R\x08priority\"\xbd\x03\n\rJobHookConfig\x12;\n\x03sql\x18\x05 \x01(\x0b\x32\'.mgmt.v1alpha1.JobHookConfig.JobSqlHookH\x00R\x03sql\x1a\xc5\x02\n\nJobSqlHook\x12\x1d\n\x05query\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05query\x12-\n\rconnection_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12\x46\n\x06timing\x18\x03 \x01(\x0b\x32..mgmt.v1alpha1.JobHookConfig.JobSqlHook.TimingR\x06timing\x1a\xa0\x01\n\x06Timing\x12@\n\x08pre_sync\x18\x03 \x01(\x0b\x32#.mgmt.v1alpha1.JobHookTimingPreSyncH\x00R\x07preSync\x12\x43\n\tpost_sync\x18\x04 \x01(\x0b\x32$.mgmt.v1alpha1.JobHookTimingPostSyncH\x00R\x08postSyncB\x0f\n\x06timing\x12\x05\xbaH\x02\x08\x01\x42\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01J\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\"\x16\n\x14JobHookTimingPreSync\"\x17\n\x15JobHookTimingPostSync\"5\n\x12GetJobHooksRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"C\n\x13GetJobHooksResponse\x12,\n\x05hooks\x18\x01 \x03(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x05hooks\"-\n\x11GetJobHookRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"@\n\x12GetJobHookResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"\\\n\x14\x43reateJobHookRequest\x12\x15\n\x06job_id\x18\x01 \x01(\tR\x05jobId\x12-\n\x04hook\x18\x02 \x01(\x0b\x32\x19.mgmt.v1alpha1.NewJobHookR\x04hook\"C\n\x15\x43reateJobHookResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"0\n\x14\x44\x65leteJobHookRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\x17\n\x15\x44\x65leteJobHookResponse\"J\n\x1dIsJobHookNameAvailableRequest\x12\x15\n\x06job_id\x18\x01 \x01(\tR\x05jobId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\"C\n\x1eIsJobHookNameAvailableResponse\x12!\n\x0cis_available\x18\x01 \x01(\x08R\x0bisAvailable\"\x81\x02\n\x14UpdateJobHookRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12-\n\x04name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12)\n\x0b\x64\x65scription\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0b\x64\x65scription\x12\x34\n\x06\x63onfig\x18\x04 \x01(\x0b\x32\x1c.mgmt.v1alpha1.JobHookConfigR\x06\x63onfig\x12\x18\n\x07\x65nabled\x18\x05 \x01(\x08R\x07\x65nabled\x12%\n\x08priority\x18\x06 \x01(\rB\t\xbaH\x06*\x04\x18\x64(\x00R\x08priority\"C\n\x15UpdateJobHookResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"N\n\x18SetJobHookEnabledRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x18\n\x07\x65nabled\x18\x02 \x01(\x08R\x07\x65nabled\"G\n\x19SetJobHookEnabledResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"\xde\x01\n GetActiveJobHooksByTimingRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12N\n\x06timing\x18\x02 \x01(\x0e\x32\x36.mgmt.v1alpha1.GetActiveJobHooksByTimingRequest.TimingR\x06timing\"I\n\x06Timing\x12\x16\n\x12TIMING_UNSPECIFIED\x10\x00\x12\x12\n\x0eTIMING_PRESYNC\x10\x01\x12\x13\n\x0fTIMING_POSTSYNC\x10\x02\"Q\n!GetActiveJobHooksByTimingResponse\x12,\n\x05hooks\x18\x01 \x03(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x05hooks*o\n\tJobStatus\x12\x1a\n\x16JOB_STATUS_UNSPECIFIED\x10\x00\x12\x16\n\x12JOB_STATUS_ENABLED\x10\x01\x12\x15\n\x11JOB_STATUS_PAUSED\x10\x03\x12\x17\n\x13JOB_STATUS_DISABLED\x10\x04*\xa7\x01\n\x0e\x41\x63tivityStatus\x12\x1f\n\x1b\x41\x43TIVITY_STATUS_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x41\x43TIVITY_STATUS_SCHEDULED\x10\x01\x12\x1b\n\x17\x41\x43TIVITY_STATUS_STARTED\x10\x02\x12\x1c\n\x18\x41\x43TIVITY_STATUS_CANCELED\x10\x03\x12\x1a\n\x16\x41\x43TIVITY_STATUS_FAILED\x10\x04*\x92\x02\n\x0cJobRunStatus\x12\x1e\n\x1aJOB_RUN_STATUS_UNSPECIFIED\x10\x00\x12\x1a\n\x16JOB_RUN_STATUS_PENDING\x10\x01\x12\x1a\n\x16JOB_RUN_STATUS_RUNNING\x10\x02\x12\x1b\n\x17JOB_RUN_STATUS_COMPLETE\x10\x03\x12\x18\n\x14JOB_RUN_STATUS_ERROR\x10\x04\x12\x1b\n\x17JOB_RUN_STATUS_CANCELED\x10\x05\x12\x1d\n\x19JOB_RUN_STATUS_TERMINATED\x10\x06\x12\x19\n\x15JOB_RUN_STATUS_FAILED\x10\x07\x12\x1c\n\x18JOB_RUN_STATUS_TIMED_OUT\x10\x08*|\n\tLogWindow\x12\"\n\x1eLOG_WINDOW_NO_TIME_UNSPECIFIED\x10\x00\x12\x1a\n\x16LOG_WINDOW_FIFTEEN_MIN\x10\x01\x12\x17\n\x13LOG_WINDOW_ONE_HOUR\x10\x02\x12\x16\n\x12LOG_WINDOW_ONE_DAY\x10\x03*w\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x01\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x02\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x03\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x04\x32\xf8\x1e\n\nJobService\x12M\n\x07GetJobs\x12\x1d.mgmt.v1alpha1.GetJobsRequest\x1a\x1e.mgmt.v1alpha1.GetJobsResponse\"\x03\x90\x02\x01\x12J\n\x06GetJob\x12\x1c.mgmt.v1alpha1.GetJobRequest\x1a\x1d.mgmt.v1alpha1.GetJobResponse\"\x03\x90\x02\x01\x12P\n\tCreateJob\x12\x1f.mgmt.v1alpha1.CreateJobRequest\x1a .mgmt.v1alpha1.CreateJobResponse\"\x00\x12P\n\tDeleteJob\x12\x1f.mgmt.v1alpha1.DeleteJobRequest\x1a .mgmt.v1alpha1.DeleteJobResponse\"\x00\x12n\n\x12IsJobNameAvailable\x12(.mgmt.v1alpha1.IsJobNameAvailableRequest\x1a).mgmt.v1alpha1.IsJobNameAvailableResponse\"\x03\x90\x02\x01\x12h\n\x11UpdateJobSchedule\x12\'.mgmt.v1alpha1.UpdateJobScheduleRequest\x1a(.mgmt.v1alpha1.UpdateJobScheduleResponse\"\x00\x12\x80\x01\n\x19UpdateJobSourceConnection\x12/.mgmt.v1alpha1.UpdateJobSourceConnectionRequest\x1a\x30.mgmt.v1alpha1.UpdateJobSourceConnectionResponse\"\x00\x12\x95\x01\n SetJobSourceSqlConnectionSubsets\x12\x36.mgmt.v1alpha1.SetJobSourceSqlConnectionSubsetsRequest\x1a\x37.mgmt.v1alpha1.SetJobSourceSqlConnectionSubsetsResponse\"\x00\x12\x8f\x01\n\x1eUpdateJobDestinationConnection\x12\x34.mgmt.v1alpha1.UpdateJobDestinationConnectionRequest\x1a\x35.mgmt.v1alpha1.UpdateJobDestinationConnectionResponse\"\x00\x12\x8f\x01\n\x1e\x44\x65leteJobDestinationConnection\x12\x34.mgmt.v1alpha1.DeleteJobDestinationConnectionRequest\x1a\x35.mgmt.v1alpha1.DeleteJobDestinationConnectionResponse\"\x00\x12\x92\x01\n\x1f\x43reateJobDestinationConnections\x12\x35.mgmt.v1alpha1.CreateJobDestinationConnectionsRequest\x1a\x36.mgmt.v1alpha1.CreateJobDestinationConnectionsResponse\"\x00\x12M\n\x08PauseJob\x12\x1e.mgmt.v1alpha1.PauseJobRequest\x1a\x1f.mgmt.v1alpha1.PauseJobResponse\"\x00\x12h\n\x10GetJobRecentRuns\x12&.mgmt.v1alpha1.GetJobRecentRunsRequest\x1a\'.mgmt.v1alpha1.GetJobRecentRunsResponse\"\x03\x90\x02\x01\x12\x62\n\x0eGetJobNextRuns\x12$.mgmt.v1alpha1.GetJobNextRunsRequest\x1a%.mgmt.v1alpha1.GetJobNextRunsResponse\"\x03\x90\x02\x01\x12\\\n\x0cGetJobStatus\x12\".mgmt.v1alpha1.GetJobStatusRequest\x1a#.mgmt.v1alpha1.GetJobStatusResponse\"\x03\x90\x02\x01\x12\x62\n\x0eGetJobStatuses\x12$.mgmt.v1alpha1.GetJobStatusesRequest\x1a%.mgmt.v1alpha1.GetJobStatusesResponse\"\x03\x90\x02\x01\x12V\n\nGetJobRuns\x12 .mgmt.v1alpha1.GetJobRunsRequest\x1a!.mgmt.v1alpha1.GetJobRunsResponse\"\x03\x90\x02\x01\x12\x65\n\x0fGetJobRunEvents\x12%.mgmt.v1alpha1.GetJobRunEventsRequest\x1a&.mgmt.v1alpha1.GetJobRunEventsResponse\"\x03\x90\x02\x01\x12S\n\tGetJobRun\x12\x1f.mgmt.v1alpha1.GetJobRunRequest\x1a .mgmt.v1alpha1.GetJobRunResponse\"\x03\x90\x02\x01\x12Y\n\x0c\x44\x65leteJobRun\x12\".mgmt.v1alpha1.DeleteJobRunRequest\x1a#.mgmt.v1alpha1.DeleteJobRunResponse\"\x00\x12Y\n\x0c\x43reateJobRun\x12\".mgmt.v1alpha1.CreateJobRunRequest\x1a#.mgmt.v1alpha1.CreateJobRunResponse\"\x00\x12Y\n\x0c\x43\x61ncelJobRun\x12\".mgmt.v1alpha1.CancelJobRunRequest\x1a#.mgmt.v1alpha1.CancelJobRunResponse\"\x00\x12\x62\n\x0fTerminateJobRun\x12%.mgmt.v1alpha1.TerminateJobRunRequest\x1a&.mgmt.v1alpha1.TerminateJobRunResponse\"\x00\x12p\n\x13GetJobRunLogsStream\x12).mgmt.v1alpha1.GetJobRunLogsStreamRequest\x1a*.mgmt.v1alpha1.GetJobRunLogsStreamResponse\"\x00\x30\x01\x12t\n\x15SetJobWorkflowOptions\x12+.mgmt.v1alpha1.SetJobWorkflowOptionsRequest\x1a,.mgmt.v1alpha1.SetJobWorkflowOptionsResponse\"\x00\x12h\n\x11SetJobSyncOptions\x12\'.mgmt.v1alpha1.SetJobSyncOptionsRequest\x1a(.mgmt.v1alpha1.SetJobSyncOptionsResponse\"\x00\x12n\n\x13ValidateJobMappings\x12).mgmt.v1alpha1.ValidateJobMappingsRequest\x1a*.mgmt.v1alpha1.ValidateJobMappingsResponse\"\x00\x12\\\n\rGetRunContext\x12#.mgmt.v1alpha1.GetRunContextRequest\x1a$.mgmt.v1alpha1.GetRunContextResponse\"\x00\x12\\\n\rSetRunContext\x12#.mgmt.v1alpha1.SetRunContextRequest\x1a$.mgmt.v1alpha1.SetRunContextResponse\"\x00\x12\x61\n\x0eSetRunContexts\x12$.mgmt.v1alpha1.SetRunContextsRequest\x1a%.mgmt.v1alpha1.SetRunContextsResponse\"\x00(\x01\x12Y\n\x0bGetJobHooks\x12!.mgmt.v1alpha1.GetJobHooksRequest\x1a\".mgmt.v1alpha1.GetJobHooksResponse\"\x03\x90\x02\x01\x12V\n\nGetJobHook\x12 .mgmt.v1alpha1.GetJobHookRequest\x1a!.mgmt.v1alpha1.GetJobHookResponse\"\x03\x90\x02\x01\x12\\\n\rCreateJobHook\x12#.mgmt.v1alpha1.CreateJobHookRequest\x1a$.mgmt.v1alpha1.CreateJobHookResponse\"\x00\x12\\\n\rDeleteJobHook\x12#.mgmt.v1alpha1.DeleteJobHookRequest\x1a$.mgmt.v1alpha1.DeleteJobHookResponse\"\x00\x12w\n\x16IsJobHookNameAvailable\x12,.mgmt.v1alpha1.IsJobHookNameAvailableRequest\x1a-.mgmt.v1alpha1.IsJobHookNameAvailableResponse\"\x00\x12\\\n\rUpdateJobHook\x12#.mgmt.v1alpha1.UpdateJobHookRequest\x1a$.mgmt.v1alpha1.UpdateJobHookResponse\"\x00\x12h\n\x11SetJobHookEnabled\x12\'.mgmt.v1alpha1.SetJobHookEnabledRequest\x1a(.mgmt.v1alpha1.SetJobHookEnabledResponse\"\x00\x12\x83\x01\n\x19GetActiveJobHooksByTiming\x12/.mgmt.v1alpha1.GetActiveJobHooksByTimingRequest\x1a\x30.mgmt.v1alpha1.GetActiveJobHooksByTimingResponse\"\x03\x90\x02\x01\x42\xc4\x01\n\x11\x63om.mgmt.v1alpha1B\x08JobProtoP\x01ZPgithub.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1;mgmtv1alpha1\xa2\x02\x03MXX\xaa\x02\rMgmt.V1alpha1\xca\x02\rMgmt\\V1alpha1\xe2\x02\x19Mgmt\\V1alpha1\\GPBMetadata\xea\x02\x0eMgmt::V1alpha1b\x06proto3')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17mgmt/v1alpha1/job.proto\x12\rmgmt.v1alpha1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1fmgmt/v1alpha1/transformer.proto\"9\n\x0eGetJobsRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"9\n\x0fGetJobsResponse\x12&\n\x04jobs\x18\x01 \x03(\x0b\x32\x12.mgmt.v1alpha1.JobR\x04jobs\"N\n\tJobSource\x12\x41\n\x07options\x18\x01 \x01(\x0b\x32\x1f.mgmt.v1alpha1.JobSourceOptionsB\x06\xbaH\x03\xc8\x01\x01R\x07options\"\xe9\x04\n\x10JobSourceOptions\x12L\n\x08postgres\x18\x01 \x01(\x0b\x32..mgmt.v1alpha1.PostgresSourceConnectionOptionsH\x00R\x08postgres\x12\x44\n\x06\x61ws_s3\x18\x02 \x01(\x0b\x32+.mgmt.v1alpha1.AwsS3SourceConnectionOptionsH\x00R\x05\x61wsS3\x12\x43\n\x05mysql\x18\x03 \x01(\x0b\x32+.mgmt.v1alpha1.MysqlSourceConnectionOptionsH\x00R\x05mysql\x12\x42\n\x08generate\x18\x04 \x01(\x0b\x32$.mgmt.v1alpha1.GenerateSourceOptionsH\x00R\x08generate\x12I\n\x0b\x61i_generate\x18\x05 \x01(\x0b\x32&.mgmt.v1alpha1.AiGenerateSourceOptionsH\x00R\naiGenerate\x12I\n\x07mongodb\x18\x06 \x01(\x0b\x32-.mgmt.v1alpha1.MongoDBSourceConnectionOptionsH\x00R\x07mongodb\x12L\n\x08\x64ynamodb\x18\x07 \x01(\x0b\x32..mgmt.v1alpha1.DynamoDBSourceConnectionOptionsH\x00R\x08\x64ynamodb\x12\x43\n\x05mssql\x18\x08 \x01(\x0b\x32+.mgmt.v1alpha1.MssqlSourceConnectionOptionsH\x00R\x05mssqlB\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01\"\x85\x01\n\x14\x43reateJobDestination\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12>\n\x07options\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.JobDestinationOptionsR\x07options\"\x8f\x01\n\x0eJobDestination\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12>\n\x07options\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.JobDestinationOptionsR\x07options\x12\x0e\n\x02id\x18\x03 \x01(\tR\x02id\"\xb6\x03\n\x17\x41iGenerateSourceOptions\x12\x32\n\x10\x61i_connection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0e\x61iConnectionId\x12O\n\x07schemas\x18\x02 \x03(\x0b\x32+.mgmt.v1alpha1.AiGenerateSourceSchemaOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x07schemas\x12\x44\n\x17\x66k_source_connection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\x14\x66kSourceConnectionId\x88\x01\x01\x12&\n\nmodel_name\x18\x04 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\tmodelName\x12$\n\x0buser_prompt\x18\x05 \x01(\tH\x01R\nuserPrompt\x88\x01\x01\x12>\n\x13generate_batch_size\x18\x06 \x01(\x03\x42\t\xbaH\x06\"\x04\x18\x64(\x01H\x02R\x11generateBatchSize\x88\x01\x01\x42\x1a\n\x18_fk_source_connection_idB\x0e\n\x0c_user_promptB\x16\n\x14_generate_batch_size\"\x8d\x01\n\x1c\x41iGenerateSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12L\n\x06tables\x18\x02 \x03(\x0b\x32*.mgmt.v1alpha1.AiGenerateSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"e\n\x1b\x41iGenerateSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12\'\n\trow_count\x18\x02 \x01(\x03\x42\n\xbaH\x07\"\x05\x18\xe8\x07(\x01R\x08rowCount\"\xce\x01\n\x15GenerateSourceOptions\x12M\n\x07schemas\x18\x01 \x03(\x0b\x32).mgmt.v1alpha1.GenerateSourceSchemaOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x07schemas\x12\x44\n\x17\x66k_source_connection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\x14\x66kSourceConnectionId\x88\x01\x01\x42\x1a\n\x18_fk_source_connection_idJ\x04\x08\x02\x10\x03\"\x89\x01\n\x1aGenerateSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12J\n\x06tables\x18\x02 \x03(\x0b\x32(.mgmt.v1alpha1.GenerateSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"`\n\x19GenerateSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12$\n\trow_count\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01R\x08rowCount\"O\n\x1eMongoDBSourceConnectionOptions\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\"\xaf\x02\n\x1f\x44ynamoDBSourceConnectionOptions\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12@\n\x06tables\x18\x02 \x03(\x0b\x32(.mgmt.v1alpha1.DynamoDBSourceTableOptionR\x06tables\x12\x65\n\x13unmapped_transforms\x18\x03 \x01(\x0b\x32\x34.mgmt.v1alpha1.DynamoDBSourceUnmappedTransformConfigR\x12unmappedTransforms\x12\x34\n\x16\x65nable_consistent_read\x18\x04 \x01(\x08R\x14\x65nableConsistentRead\"\x8f\x02\n%DynamoDBSourceUnmappedTransformConfig\x12\x32\n\x01\x62\x18\x01 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x01\x62\x12>\n\x07\x62oolean\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x07\x62oolean\x12\x32\n\x01n\x18\x04 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x01n\x12\x32\n\x01s\x18\x06 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x01sJ\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06\"s\n\x19\x44ynamoDBSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"\xaf\x08\n\x1fPostgresSourceConnectionOptions\x12\x43\n\x07schemas\x18\x02 \x03(\x0b\x32).mgmt.v1alpha1.PostgresSourceSchemaOptionR\x07schemas\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12H\n!subset_by_foreign_key_constraints\x18\x04 \x01(\x08R\x1dsubsetByForeignKeyConstraints\x12\x89\x01\n\x1cnew_column_addition_strategy\x18\x05 \x01(\x0b\x32H.mgmt.v1alpha1.PostgresSourceConnectionOptions.NewColumnAdditionStrategyR\x19newColumnAdditionStrategy\x12|\n\x17\x63olumn_removal_strategy\x18\x06 \x01(\x0b\x32\x44.mgmt.v1alpha1.PostgresSourceConnectionOptions.ColumnRemovalStrategyR\x15\x63olumnRemovalStrategy\x1a\x9b\x02\n\x19NewColumnAdditionStrategy\x12m\n\x08halt_job\x18\x01 \x01(\x0b\x32P.mgmt.v1alpha1.PostgresSourceConnectionOptions.NewColumnAdditionStrategy.HaltJobH\x00R\x07haltJob\x12m\n\x08\x61uto_map\x18\x02 \x01(\x0b\x32P.mgmt.v1alpha1.PostgresSourceConnectionOptions.NewColumnAdditionStrategy.AutoMapH\x00R\x07\x61utoMap\x1a\t\n\x07HaltJob\x1a\t\n\x07\x41utoMapB\n\n\x08strategy\x1a\x9f\x02\n\x15\x43olumnRemovalStrategy\x12i\n\x08halt_job\x18\x01 \x01(\x0b\x32L.mgmt.v1alpha1.PostgresSourceConnectionOptions.ColumnRemovalStrategy.HaltJobH\x00R\x07haltJob\x12u\n\x0c\x63ontinue_job\x18\x02 \x01(\x0b\x32P.mgmt.v1alpha1.PostgresSourceConnectionOptions.ColumnRemovalStrategy.ContinueJobH\x00R\x0b\x63ontinueJob\x1a\t\n\x07HaltJob\x1a\r\n\x0b\x43ontinueJobB\n\n\x08strategyJ\x04\x08\x01\x10\x02\"\x89\x01\n\x1aPostgresSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12J\n\x06tables\x18\x02 \x03(\x0b\x32(.mgmt.v1alpha1.PostgresSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"s\n\x19PostgresSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"\xae\x05\n\x1cMysqlSourceConnectionOptions\x12<\n\x1bhalt_on_new_column_addition\x18\x01 \x01(\x08R\x17haltOnNewColumnAddition\x12@\n\x07schemas\x18\x02 \x03(\x0b\x32&.mgmt.v1alpha1.MysqlSourceSchemaOptionR\x07schemas\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12H\n!subset_by_foreign_key_constraints\x18\x04 \x01(\x08R\x1dsubsetByForeignKeyConstraints\x12y\n\x17\x63olumn_removal_strategy\x18\x05 \x01(\x0b\x32\x41.mgmt.v1alpha1.MysqlSourceConnectionOptions.ColumnRemovalStrategyR\x15\x63olumnRemovalStrategy\x1a\x99\x02\n\x15\x43olumnRemovalStrategy\x12\x66\n\x08halt_job\x18\x01 \x01(\x0b\x32I.mgmt.v1alpha1.MysqlSourceConnectionOptions.ColumnRemovalStrategy.HaltJobH\x00R\x07haltJob\x12r\n\x0c\x63ontinue_job\x18\x02 \x01(\x0b\x32M.mgmt.v1alpha1.MysqlSourceConnectionOptions.ColumnRemovalStrategy.ContinueJobH\x00R\x0b\x63ontinueJob\x1a\t\n\x07HaltJob\x1a\r\n\x0b\x43ontinueJobB\n\n\x08strategy\"\x83\x01\n\x17MysqlSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12G\n\x06tables\x18\x02 \x03(\x0b\x32%.mgmt.v1alpha1.MysqlSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"p\n\x16MysqlSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"\xae\x05\n\x1cMssqlSourceConnectionOptions\x12<\n\x1bhalt_on_new_column_addition\x18\x01 \x01(\x08R\x17haltOnNewColumnAddition\x12@\n\x07schemas\x18\x02 \x03(\x0b\x32&.mgmt.v1alpha1.MssqlSourceSchemaOptionR\x07schemas\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12H\n!subset_by_foreign_key_constraints\x18\x04 \x01(\x08R\x1dsubsetByForeignKeyConstraints\x12y\n\x17\x63olumn_removal_strategy\x18\x05 \x01(\x0b\x32\x41.mgmt.v1alpha1.MssqlSourceConnectionOptions.ColumnRemovalStrategyR\x15\x63olumnRemovalStrategy\x1a\x99\x02\n\x15\x43olumnRemovalStrategy\x12\x66\n\x08halt_job\x18\x01 \x01(\x0b\x32I.mgmt.v1alpha1.MssqlSourceConnectionOptions.ColumnRemovalStrategy.HaltJobH\x00R\x07haltJob\x12r\n\x0c\x63ontinue_job\x18\x02 \x01(\x0b\x32M.mgmt.v1alpha1.MssqlSourceConnectionOptions.ColumnRemovalStrategy.ContinueJobH\x00R\x0b\x63ontinueJob\x1a\t\n\x07HaltJob\x1a\r\n\x0b\x43ontinueJobB\n\n\x08strategy\"\x83\x01\n\x17MssqlSourceSchemaOption\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12G\n\x06tables\x18\x02 \x03(\x0b\x32%.mgmt.v1alpha1.MssqlSourceTableOptionB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x06tables\"p\n\x16MssqlSourceTableOption\x12\x1d\n\x05table\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12&\n\x0cwhere_clause\x18\x02 \x01(\tH\x00R\x0bwhereClause\x88\x01\x01\x42\x0f\n\r_where_clause\"M\n\x1c\x41wsS3SourceConnectionOptions\x12-\n\rconnection_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\"\xcf\x05\n\x15JobDestinationOptions\x12`\n\x10postgres_options\x18\x01 \x01(\x0b\x32\x33.mgmt.v1alpha1.PostgresDestinationConnectionOptionsH\x00R\x0fpostgresOptions\x12X\n\x0e\x61ws_s3_options\x18\x02 \x01(\x0b\x32\x30.mgmt.v1alpha1.AwsS3DestinationConnectionOptionsH\x00R\x0c\x61wsS3Options\x12W\n\rmysql_options\x18\x03 \x01(\x0b\x32\x30.mgmt.v1alpha1.MysqlDestinationConnectionOptionsH\x00R\x0cmysqlOptions\x12]\n\x0fmongodb_options\x18\x04 \x01(\x0b\x32\x32.mgmt.v1alpha1.MongoDBDestinationConnectionOptionsH\x00R\x0emongodbOptions\x12v\n\x18gcp_cloudstorage_options\x18\x05 \x01(\x0b\x32:.mgmt.v1alpha1.GcpCloudStorageDestinationConnectionOptionsH\x00R\x16gcpCloudstorageOptions\x12`\n\x10\x64ynamodb_options\x18\x06 \x01(\x0b\x32\x33.mgmt.v1alpha1.DynamoDBDestinationConnectionOptionsH\x00R\x0f\x64ynamodbOptions\x12W\n\rmssql_options\x18\x07 \x01(\x0b\x32\x30.mgmt.v1alpha1.MssqlDestinationConnectionOptionsH\x00R\x0cmssqlOptionsB\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01\"%\n#MongoDBDestinationConnectionOptions\"-\n+GcpCloudStorageDestinationConnectionOptions\"}\n$DynamoDBDestinationConnectionOptions\x12U\n\x0etable_mappings\x18\x01 \x03(\x0b\x32..mgmt.v1alpha1.DynamoDBDestinationTableMappingR\rtableMappings\"q\n\x1f\x44ynamoDBDestinationTableMapping\x12!\n\x0csource_table\x18\x01 \x01(\tR\x0bsourceTable\x12+\n\x11\x64\x65stination_table\x18\x02 \x01(\tR\x10\x64\x65stinationTable\"\xa4\x03\n$PostgresDestinationConnectionOptions\x12Q\n\x0etruncate_table\x18\x01 \x01(\x0b\x32*.mgmt.v1alpha1.PostgresTruncateTableConfigR\rtruncateTable\x12*\n\x11init_table_schema\x18\x02 \x01(\x08R\x0finitTableSchema\x12H\n\x0bon_conflict\x18\x03 \x01(\x0b\x32\'.mgmt.v1alpha1.PostgresOnConflictConfigR\nonConflict\x12=\n\x1bskip_foreign_key_violations\x18\x04 \x01(\x08R\x18skipForeignKeyViolations\x12\x30\n\x05\x62\x61tch\x18\x05 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\x12\x30\n\rmax_in_flight\x18\x06 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x42\x10\n\x0e_max_in_flight\"\xc4\x02\n\x18PostgresOnConflictConfig\x12\x1d\n\ndo_nothing\x18\x01 \x01(\x08R\tdoNothing\x12_\n\x07nothing\x18\x02 \x01(\x0b\x32\x43.mgmt.v1alpha1.PostgresOnConflictConfig.PostgresOnConflictDoNothingH\x00R\x07nothing\x12Z\n\x06update\x18\x03 \x01(\x0b\x32@.mgmt.v1alpha1.PostgresOnConflictConfig.PostgresOnConflictUpdateH\x00R\x06update\x1a\x1d\n\x1bPostgresOnConflictDoNothing\x1a\x1a\n\x18PostgresOnConflictUpdateB\x11\n\x08strategy\x12\x05\xbaH\x02\x08\x00\"m\n\x1bPostgresTruncateTableConfig\x12\x34\n\x16truncate_before_insert\x18\x01 \x01(\x08R\x14truncateBeforeInsert\x12\x18\n\x07\x63\x61scade\x18\x02 \x01(\x08R\x07\x63\x61scade\"\x9b\x03\n!MysqlDestinationConnectionOptions\x12N\n\x0etruncate_table\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.MysqlTruncateTableConfigR\rtruncateTable\x12*\n\x11init_table_schema\x18\x02 \x01(\x08R\x0finitTableSchema\x12\x45\n\x0bon_conflict\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.MysqlOnConflictConfigR\nonConflict\x12=\n\x1bskip_foreign_key_violations\x18\x04 \x01(\x08R\x18skipForeignKeyViolations\x12\x30\n\x05\x62\x61tch\x18\x05 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\x12\x30\n\rmax_in_flight\x18\x06 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x42\x10\n\x0e_max_in_flight\"P\n\x18MysqlTruncateTableConfig\x12\x34\n\x16truncate_before_insert\x18\x01 \x01(\x08R\x14truncateBeforeInsert\"\xaf\x02\n\x15MysqlOnConflictConfig\x12\x1d\n\ndo_nothing\x18\x01 \x01(\x08R\tdoNothing\x12Y\n\x07nothing\x18\x02 \x01(\x0b\x32=.mgmt.v1alpha1.MysqlOnConflictConfig.MysqlOnConflictDoNothingH\x00R\x07nothing\x12T\n\x06update\x18\x03 \x01(\x0b\x32:.mgmt.v1alpha1.MysqlOnConflictConfig.MysqlOnConflictUpdateH\x00R\x06update\x1a\x1a\n\x18MysqlOnConflictDoNothing\x1a\x17\n\x15MysqlOnConflictUpdateB\x11\n\x08strategy\x12\x05\xbaH\x02\x08\x00\"\x9b\x03\n!MssqlDestinationConnectionOptions\x12N\n\x0etruncate_table\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.MssqlTruncateTableConfigR\rtruncateTable\x12*\n\x11init_table_schema\x18\x02 \x01(\x08R\x0finitTableSchema\x12\x45\n\x0bon_conflict\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.MssqlOnConflictConfigR\nonConflict\x12=\n\x1bskip_foreign_key_violations\x18\x04 \x01(\x08R\x18skipForeignKeyViolations\x12\x30\n\x05\x62\x61tch\x18\x05 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\x12\x30\n\rmax_in_flight\x18\x06 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x42\x10\n\x0e_max_in_flight\"P\n\x18MssqlTruncateTableConfig\x12\x34\n\x16truncate_before_insert\x18\x01 \x01(\x08R\x14truncateBeforeInsert\"6\n\x15MssqlOnConflictConfig\x12\x1d\n\ndo_nothing\x18\x01 \x01(\x08R\tdoNothing\"\xb9\x04\n!AwsS3DestinationConnectionOptions\x12\x62\n\rstorage_class\x18\x01 \x01(\x0e\x32=.mgmt.v1alpha1.AwsS3DestinationConnectionOptions.StorageClassR\x0cstorageClass\x12\x30\n\rmax_in_flight\x18\x02 \x01(\rB\x07\xbaH\x04*\x02(\x01H\x00R\x0bmaxInFlight\x88\x01\x01\x12\x1d\n\x07timeout\x18\x03 \x01(\tH\x01R\x07timeout\x88\x01\x01\x12\x30\n\x05\x62\x61tch\x18\x04 \x01(\x0b\x32\x1a.mgmt.v1alpha1.BatchConfigR\x05\x62\x61tch\"\x8e\x02\n\x0cStorageClass\x12\x1d\n\x19STORAGE_CLASS_UNSPECIFIED\x10\x00\x12\x1a\n\x16STORAGE_CLASS_STANDARD\x10\x01\x12$\n STORAGE_CLASS_REDUCED_REDUNDANCY\x10\x02\x12\x19\n\x15STORAGE_CLASS_GLACIER\x10\x03\x12\x1d\n\x19STORAGE_CLASS_STANDARD_IA\x10\x04\x12\x1c\n\x18STORAGE_CLASS_ONEZONE_IA\x10\x05\x12%\n!STORAGE_CLASS_INTELLIGENT_TIERING\x10\x06\x12\x1e\n\x1aSTORAGE_CLASS_DEEP_ARCHIVE\x10\x07\x42\x10\n\x0e_max_in_flightB\n\n\x08_timeout\"Z\n\x0b\x42\x61tchConfig\x12\x19\n\x05\x63ount\x18\x01 \x01(\rH\x00R\x05\x63ount\x88\x01\x01\x12\x1b\n\x06period\x18\x02 \x01(\tH\x01R\x06period\x88\x01\x01\x42\x08\n\x06_countB\t\n\x07_period\"\xf2\x04\n\x10\x43reateJobRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x34\n\x08job_name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x07jobName\x12(\n\rcron_schedule\x18\x03 \x01(\tH\x00R\x0c\x63ronSchedule\x88\x01\x01\x12\x35\n\x08mappings\x18\x04 \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12\x30\n\x06source\x18\x05 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceR\x06source\x12G\n\x0c\x64\x65stinations\x18\x06 \x03(\x0b\x32#.mgmt.v1alpha1.CreateJobDestinationR\x0c\x64\x65stinations\x12(\n\x10initiate_job_run\x18\x07 \x01(\x08R\x0einitiateJobRun\x12I\n\x10workflow_options\x18\x08 \x01(\x0b\x32\x1e.mgmt.v1alpha1.WorkflowOptionsR\x0fworkflowOptions\x12\x41\n\x0csync_options\x18\t \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityOptionsR\x0bsyncOptions\x12Y\n\x14virtual_foreign_keys\x18\n \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeysB\x10\n\x0e_cron_schedule\"q\n\x0fWorkflowOptions\x12$\n\x0brun_timeout\x18\x08 \x01(\x03H\x00R\nrunTimeout\x88\x01\x01\x42\x0e\n\x0c_run_timeoutJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x05\x10\x06J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08\"\x95\x02\n\x0f\x41\x63tivityOptions\x12G\n\x19schedule_to_close_timeout\x18\x01 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x16scheduleToCloseTimeout\x88\x01\x01\x12\x41\n\x16start_to_close_timeout\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x01R\x13startToCloseTimeout\x88\x01\x01\x12=\n\x0cretry_policy\x18\x03 \x01(\x0b\x32\x1a.mgmt.v1alpha1.RetryPolicyR\x0bretryPolicyB\x1c\n\x1a_schedule_to_close_timeoutB\x19\n\x17_start_to_close_timeout\"[\n\x0bRetryPolicy\x12\x37\n\x10maximum_attempts\x18\x01 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00H\x00R\x0fmaximumAttempts\x88\x01\x01\x42\x13\n\x11_maximum_attempts\"9\n\x11\x43reateJobResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"W\n\x15JobMappingTransformer\x12\x38\n\x06\x63onfig\x18\x03 \x01(\x0b\x32 .mgmt.v1alpha1.TransformerConfigR\x06\x63onfigJ\x04\x08\x01\x10\x02\"\xb5\x01\n\nJobMapping\x12\x1f\n\x06schema\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06schema\x12\x1d\n\x05table\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05table\x12\x1f\n\x06\x63olumn\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06\x63olumn\x12\x46\n\x0btransformer\x18\x05 \x01(\x0b\x32$.mgmt.v1alpha1.JobMappingTransformerR\x0btransformer\")\n\rGetJobRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"6\n\x0eGetJobResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"p\n\x18UpdateJobScheduleRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12(\n\rcron_schedule\x18\x02 \x01(\tH\x00R\x0c\x63ronSchedule\x88\x01\x01\x42\x10\n\x0e_cron_schedule\"A\n\x19UpdateJobScheduleResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"c\n\x0fPauseJobRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x14\n\x05pause\x18\x02 \x01(\x08R\x05pause\x12\x17\n\x04note\x18\x03 \x01(\tH\x00R\x04note\x88\x01\x01\x42\x07\n\x05_note\"8\n\x10PauseJobResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"\x80\x02\n UpdateJobSourceConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x30\n\x06source\x18\x02 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceR\x06source\x12\x35\n\x08mappings\x18\x03 \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12Y\n\x14virtual_foreign_keys\x18\x04 \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeys\"I\n!UpdateJobSourceConnectionResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"r\n\x1aPostgresSourceSchemaSubset\x12T\n\x10postgres_schemas\x18\x01 \x03(\x0b\x32).mgmt.v1alpha1.PostgresSourceSchemaOptionR\x0fpostgresSchemas\"f\n\x17MysqlSourceSchemaSubset\x12K\n\rmysql_schemas\x18\x01 \x03(\x0b\x32&.mgmt.v1alpha1.MysqlSourceSchemaOptionR\x0cmysqlSchemas\"^\n\x1a\x44ynamoDBSourceSchemaSubset\x12@\n\x06tables\x18\x01 \x03(\x0b\x32(.mgmt.v1alpha1.DynamoDBSourceTableOptionR\x06tables\"f\n\x17MssqlSourceSchemaSubset\x12K\n\rmssql_schemas\x18\x01 \x03(\x0b\x32&.mgmt.v1alpha1.MssqlSourceSchemaOptionR\x0cmssqlSchemas\"\xf8\x02\n\x18JobSourceSqlSubetSchemas\x12T\n\x0fpostgres_subset\x18\x02 \x01(\x0b\x32).mgmt.v1alpha1.PostgresSourceSchemaSubsetH\x00R\x0epostgresSubset\x12K\n\x0cmysql_subset\x18\x03 \x01(\x0b\x32&.mgmt.v1alpha1.MysqlSourceSchemaSubsetH\x00R\x0bmysqlSubset\x12T\n\x0f\x64ynamodb_subset\x18\x04 \x01(\x0b\x32).mgmt.v1alpha1.DynamoDBSourceSchemaSubsetH\x00R\x0e\x64ynamodbSubset\x12K\n\x0cmssql_subset\x18\x05 \x01(\x0b\x32&.mgmt.v1alpha1.MssqlSourceSchemaSubsetH\x00R\x0bmssqlSubsetB\x10\n\x07schemas\x12\x05\xbaH\x02\x08\x01J\x04\x08\x01\x10\x02\"\xd0\x01\n\'SetJobSourceSqlConnectionSubsetsRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x41\n\x07schemas\x18\x02 \x01(\x0b\x32\'.mgmt.v1alpha1.JobSourceSqlSubetSchemasR\x07schemas\x12H\n!subset_by_foreign_key_constraints\x18\x03 \x01(\x08R\x1dsubsetByForeignKeyConstraints\"P\n(SetJobSourceSqlConnectionSubsetsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"\xde\x01\n%UpdateJobDestinationConnectionRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12-\n\rconnection_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12>\n\x07options\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.JobDestinationOptionsR\x07options\x12%\n\x0e\x64\x65stination_id\x18\x04 \x01(\tR\rdestinationId\"N\n&UpdateJobDestinationConnectionResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"X\n%DeleteJobDestinationConnectionRequest\x12/\n\x0e\x64\x65stination_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\rdestinationId\"(\n&DeleteJobDestinationConnectionResponse\"\x92\x01\n&CreateJobDestinationConnectionsRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12G\n\x0c\x64\x65stinations\x18\x02 \x03(\x0b\x32#.mgmt.v1alpha1.CreateJobDestinationR\x0c\x64\x65stinations\"O\n\'CreateJobDestinationConnectionsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\",\n\x10\x44\x65leteJobRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\x13\n\x11\x44\x65leteJobResponse\"s\n\x19IsJobNameAvailableRequest\x12-\n\x04name\x18\x01 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"?\n\x1aIsJobNameAvailableResponse\x12!\n\x0cis_available\x18\x01 \x01(\x08R\x0bisAvailable\"g\n\x11GetJobRunsRequest\x12!\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\x05jobId\x12)\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01H\x00R\taccountIdB\x04\n\x02id\"F\n\x12GetJobRunsResponse\x12\x30\n\x08job_runs\x18\x01 \x03(\x0b\x32\x15.mgmt.v1alpha1.JobRunR\x07jobRuns\"Y\n\x10GetJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"C\n\x11GetJobRunResponse\x12.\n\x07job_run\x18\x01 \x01(\x0b\x32\x15.mgmt.v1alpha1.JobRunR\x06jobRun\"6\n\x13\x43reateJobRunRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"\x16\n\x14\x43reateJobRunResponse\"\\\n\x13\x43\x61ncelJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"\x16\n\x14\x43\x61ncelJobRunResponse\"\xe9\x05\n\x03Job\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12+\n\x12\x63reated_by_user_id\x18\x02 \x01(\tR\x0f\x63reatedByUserId\x12\x39\n\ncreated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n\x12updated_by_user_id\x18\x04 \x01(\tR\x0fupdatedByUserId\x12\x39\n\nupdated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x12\n\x04name\x18\x06 \x01(\tR\x04name\x12\x30\n\x06source\x18\x07 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceR\x06source\x12\x41\n\x0c\x64\x65stinations\x18\x08 \x03(\x0b\x32\x1d.mgmt.v1alpha1.JobDestinationR\x0c\x64\x65stinations\x12\x35\n\x08mappings\x18\t \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12(\n\rcron_schedule\x18\n \x01(\tH\x00R\x0c\x63ronSchedule\x88\x01\x01\x12\x1d\n\naccount_id\x18\x0b \x01(\tR\taccountId\x12\x41\n\x0csync_options\x18\x0c \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityOptionsR\x0bsyncOptions\x12I\n\x10workflow_options\x18\r \x01(\x0b\x32\x1e.mgmt.v1alpha1.WorkflowOptionsR\x0fworkflowOptions\x12Y\n\x14virtual_foreign_keys\x18\x0e \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeysB\x10\n\x0e_cron_schedule\"g\n\x0cJobRecentRun\x12\x39\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12\x1c\n\njob_run_id\x18\x02 \x01(\tR\x08jobRunId\":\n\x17GetJobRecentRunsRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"X\n\x18GetJobRecentRunsResponse\x12<\n\x0brecent_runs\x18\x01 \x03(\x0b\x32\x1b.mgmt.v1alpha1.JobRecentRunR\nrecentRuns\"O\n\x0bJobNextRuns\x12@\n\x0enext_run_times\x18\x01 \x03(\x0b\x32\x1a.google.protobuf.TimestampR\x0cnextRunTimes\"8\n\x15GetJobNextRunsRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"Q\n\x16GetJobNextRunsResponse\x12\x37\n\tnext_runs\x18\x01 \x01(\x0b\x32\x1a.mgmt.v1alpha1.JobNextRunsR\x08nextRuns\"6\n\x13GetJobStatusRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"H\n\x14GetJobStatusResponse\x12\x30\n\x06status\x18\x01 \x01(\x0e\x32\x18.mgmt.v1alpha1.JobStatusR\x06status\"d\n\x0fJobStatusRecord\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12\x30\n\x06status\x18\x02 \x01(\x0e\x32\x18.mgmt.v1alpha1.JobStatusR\x06status\"@\n\x15GetJobStatusesRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"T\n\x16GetJobStatusesResponse\x12:\n\x08statuses\x18\x01 \x03(\x0b\x32\x1e.mgmt.v1alpha1.JobStatusRecordR\x08statuses\"+\n\x0f\x41\x63tivityFailure\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\"\xc6\x01\n\x0fPendingActivity\x12\x35\n\x06status\x18\x01 \x01(\x0e\x32\x1d.mgmt.v1alpha1.ActivityStatusR\x06status\x12#\n\ractivity_name\x18\x02 \x01(\tR\x0c\x61\x63tivityName\x12\x46\n\x0clast_failure\x18\x03 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityFailureH\x00R\x0blastFailure\x88\x01\x01\x42\x0f\n\r_last_failure\"\xdd\x02\n\x06JobRun\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12\x33\n\x06status\x18\x04 \x01(\x0e\x32\x1b.mgmt.v1alpha1.JobRunStatusR\x06status\x12\x39\n\nstarted_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartedAt\x12\x42\n\x0c\x63ompleted_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\x0b\x63ompletedAt\x88\x01\x01\x12M\n\x12pending_activities\x18\x08 \x03(\x0b\x32\x1e.mgmt.v1alpha1.PendingActivityR\x11pendingActivitiesB\x0f\n\r_completed_atJ\x04\x08\x05\x10\x06\"Q\n\x14JobRunEventTaskError\x12\x18\n\x07message\x18\x01 \x01(\tR\x07message\x12\x1f\n\x0bretry_state\x18\x02 \x01(\tR\nretryState\"\xab\x01\n\x0fJobRunEventTask\x12\x0e\n\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n\x04type\x18\x02 \x01(\tR\x04type\x12\x39\n\nevent_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\teventTime\x12\x39\n\x05\x65rror\x18\x04 \x01(\x0b\x32#.mgmt.v1alpha1.JobRunEventTaskErrorR\x05\x65rror\"B\n\x12JobRunSyncMetadata\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\"r\n\x13JobRunEventMetadata\x12H\n\rsync_metadata\x18\x01 \x01(\x0b\x32!.mgmt.v1alpha1.JobRunSyncMetadataH\x00R\x0csyncMetadataB\x11\n\x08metadata\x12\x05\xbaH\x02\x08\x01\"\x9d\x02\n\x0bJobRunEvent\x12\x0e\n\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n\x04type\x18\x02 \x01(\tR\x04type\x12\x39\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12\x39\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcloseTime\x12>\n\x08metadata\x18\x05 \x01(\x0b\x32\".mgmt.v1alpha1.JobRunEventMetadataR\x08metadata\x12\x34\n\x05tasks\x18\x06 \x03(\x0b\x32\x1e.mgmt.v1alpha1.JobRunEventTaskR\x05tasks\"_\n\x16GetJobRunEventsRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"u\n\x17GetJobRunEventsResponse\x12\x32\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1a.mgmt.v1alpha1.JobRunEventR\x06\x65vents\x12&\n\x0fis_run_complete\x18\x02 \x01(\x08R\risRunComplete\"\\\n\x13\x44\x65leteJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"\x16\n\x14\x44\x65leteJobRunResponse\"_\n\x16TerminateJobRunRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\"\x19\n\x17TerminateJobRunResponse\"\xb2\x02\n\x1aGetJobRunLogsStreamRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x30\n\x06window\x18\x03 \x01(\x0e\x32\x18.mgmt.v1alpha1.LogWindowR\x06window\x12\x1f\n\x0bshould_tail\x18\x04 \x01(\x08R\nshouldTail\x12\x30\n\rmax_log_lines\x18\x05 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x0bmaxLogLines\x88\x01\x01\x12\x36\n\nlog_levels\x18\x06 \x03(\x0e\x32\x17.mgmt.v1alpha1.LogLevelR\tlogLevelsB\x10\n\x0e_max_log_lines\"\x85\x01\n\x1bGetJobRunLogsStreamResponse\x12\x19\n\x08log_line\x18\x01 \x01(\tR\x07logLine\x12=\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\ttimestamp\x88\x01\x01\x42\x0c\n\n_timestamp\"\x8b\x02\n\x14GetJobRunLogsRequest\x12\x1c\n\njob_run_id\x18\x01 \x01(\tR\x08jobRunId\x12\'\n\naccount_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x30\n\x06window\x18\x03 \x01(\x0e\x32\x18.mgmt.v1alpha1.LogWindowR\x06window\x12\x30\n\rmax_log_lines\x18\x04 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x0bmaxLogLines\x88\x01\x01\x12\x36\n\nlog_levels\x18\x05 \x03(\x0e\x32\x17.mgmt.v1alpha1.LogLevelR\tlogLevelsB\x10\n\x0e_max_log_lines\"\xd5\x01\n\x15GetJobRunLogsResponse\x12I\n\tlog_lines\x18\x01 \x03(\x0b\x32,.mgmt.v1alpha1.GetJobRunLogsResponse.LogLineR\x08logLines\x1aq\n\x07LogLine\x12\x19\n\x08log_line\x18\x01 \x01(\tR\x07logLine\x12=\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\ttimestamp\x88\x01\x01\x42\x0c\n\n_timestamp\"\x83\x01\n\x1cSetJobWorkflowOptionsRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12I\n\x10worfklow_options\x18\x02 \x01(\x0b\x32\x1e.mgmt.v1alpha1.WorkflowOptionsR\x0fworfklowOptions\"E\n\x1dSetJobWorkflowOptionsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"w\n\x18SetJobSyncOptionsRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x41\n\x0csync_options\x18\x02 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ActivityOptionsR\x0bsyncOptions\"A\n\x19SetJobSyncOptionsResponse\x12$\n\x03job\x18\x01 \x01(\x0b\x32\x12.mgmt.v1alpha1.JobR\x03job\"\xd3\x02\n\x1aValidateJobMappingsRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x35\n\x08mappings\x18\x02 \x03(\x0b\x32\x19.mgmt.v1alpha1.JobMappingR\x08mappings\x12-\n\rconnection_id\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12Y\n\x14virtual_foreign_keys\x18\x04 \x03(\x0b\x32\'.mgmt.v1alpha1.VirtualForeignConstraintR\x12virtualForeignKeys\x12<\n\njob_source\x18\x05 \x01(\x0b\x32\x18.mgmt.v1alpha1.JobSourceH\x00R\tjobSource\x88\x01\x01\x42\r\n\x0b_job_source\"k\n\x0b\x43olumnError\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x16\n\x06\x63olumn\x18\x03 \x01(\tR\x06\x63olumn\x12\x16\n\x06\x65rrors\x18\x04 \x03(\tR\x06\x65rrors\"q\n\rColumnWarning\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x16\n\x06\x63olumn\x18\x03 \x01(\tR\x06\x63olumn\x12\x1a\n\x08warnings\x18\x05 \x03(\tR\x08warnings\"\'\n\rDatabaseError\x12\x16\n\x06\x65rrors\x18\x01 \x03(\tR\x06\x65rrors\"\xec\x01\n\x1bValidateJobMappingsResponse\x12?\n\rcolumn_errors\x18\x01 \x03(\x0b\x32\x1a.mgmt.v1alpha1.ColumnErrorR\x0c\x63olumnErrors\x12\x45\n\x0f\x64\x61tabase_errors\x18\x02 \x01(\x0b\x32\x1c.mgmt.v1alpha1.DatabaseErrorR\x0e\x64\x61tabaseErrors\x12\x45\n\x0f\x63olumn_warnings\x18\x03 \x03(\x0b\x32\x1c.mgmt.v1alpha1.ColumnWarningR\x0e\x63olumnWarnings\"[\n\x11VirtualForeignKey\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x18\n\x07\x63olumns\x18\x03 \x03(\tR\x07\x63olumns\"\xa5\x01\n\x18VirtualForeignConstraint\x12\x16\n\x06schema\x18\x01 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x02 \x01(\tR\x05table\x12\x18\n\x07\x63olumns\x18\x03 \x03(\tR\x07\x63olumns\x12\x41\n\x0b\x66oreign_key\x18\x04 \x01(\x0b\x32 .mgmt.v1alpha1.VirtualForeignKeyR\nforeignKey\"\x88\x01\n\rRunContextKey\x12%\n\njob_run_id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08jobRunId\x12(\n\x0b\x65xternal_id\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\nexternalId\x12&\n\naccount_id\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\taccountId\"D\n\x14GetRunContextRequest\x12,\n\x02id\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.RunContextKeyR\x02id\"-\n\x15GetRunContextResponse\x12\x14\n\x05value\x18\x01 \x01(\x0cR\x05value\"Z\n\x14SetRunContextRequest\x12,\n\x02id\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.RunContextKeyR\x02id\x12\x14\n\x05value\x18\x02 \x01(\x0cR\x05value\"\x17\n\x15SetRunContextResponse\"[\n\x15SetRunContextsRequest\x12,\n\x02id\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.RunContextKeyR\x02id\x12\x14\n\x05value\x18\x02 \x01(\x0cR\x05value\"\x18\n\x16SetRunContextsResponse\"\xad\x03\n\x07JobHook\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12\x15\n\x06job_id\x18\x04 \x01(\tR\x05jobId\x12\x34\n\x06\x63onfig\x18\x05 \x01(\x0b\x32\x1c.mgmt.v1alpha1.JobHookConfigR\x06\x63onfig\x12+\n\x12\x63reated_by_user_id\x18\x06 \x01(\tR\x0f\x63reatedByUserId\x12\x39\n\ncreated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n\x12updated_by_user_id\x18\x08 \x01(\tR\x0fupdatedByUserId\x12\x39\n\nupdated_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x18\n\x07\x65nabled\x18\n \x01(\x08R\x07\x65nabled\x12%\n\x08priority\x18\x0b \x01(\rB\t\xbaH\x06*\x04\x18\x64(\x00R\x08priority\"\xdd\x01\n\nNewJobHook\x12-\n\x04name\x18\x01 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12)\n\x0b\x64\x65scription\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0b\x64\x65scription\x12\x34\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x1c.mgmt.v1alpha1.JobHookConfigR\x06\x63onfig\x12\x18\n\x07\x65nabled\x18\x04 \x01(\x08R\x07\x65nabled\x12%\n\x08priority\x18\x05 \x01(\rB\t\xbaH\x06*\x04\x18\x64(\x00R\x08priority\"\xbd\x03\n\rJobHookConfig\x12;\n\x03sql\x18\x05 \x01(\x0b\x32\'.mgmt.v1alpha1.JobHookConfig.JobSqlHookH\x00R\x03sql\x1a\xc5\x02\n\nJobSqlHook\x12\x1d\n\x05query\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05query\x12-\n\rconnection_id\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x0c\x63onnectionId\x12\x46\n\x06timing\x18\x03 \x01(\x0b\x32..mgmt.v1alpha1.JobHookConfig.JobSqlHook.TimingR\x06timing\x1a\xa0\x01\n\x06Timing\x12@\n\x08pre_sync\x18\x03 \x01(\x0b\x32#.mgmt.v1alpha1.JobHookTimingPreSyncH\x00R\x07preSync\x12\x43\n\tpost_sync\x18\x04 \x01(\x0b\x32$.mgmt.v1alpha1.JobHookTimingPostSyncH\x00R\x08postSyncB\x0f\n\x06timing\x12\x05\xbaH\x02\x08\x01\x42\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01J\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\"\x16\n\x14JobHookTimingPreSync\"\x17\n\x15JobHookTimingPostSync\"5\n\x12GetJobHooksRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\"C\n\x13GetJobHooksResponse\x12,\n\x05hooks\x18\x01 \x03(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x05hooks\"-\n\x11GetJobHookRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"@\n\x12GetJobHookResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"\\\n\x14\x43reateJobHookRequest\x12\x15\n\x06job_id\x18\x01 \x01(\tR\x05jobId\x12-\n\x04hook\x18\x02 \x01(\x0b\x32\x19.mgmt.v1alpha1.NewJobHookR\x04hook\"C\n\x15\x43reateJobHookResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"0\n\x14\x44\x65leteJobHookRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\x17\n\x15\x44\x65leteJobHookResponse\"J\n\x1dIsJobHookNameAvailableRequest\x12\x15\n\x06job_id\x18\x01 \x01(\tR\x05jobId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\"C\n\x1eIsJobHookNameAvailableResponse\x12!\n\x0cis_available\x18\x01 \x01(\x08R\x0bisAvailable\"\x81\x02\n\x14UpdateJobHookRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12-\n\x04name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12)\n\x0b\x64\x65scription\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0b\x64\x65scription\x12\x34\n\x06\x63onfig\x18\x04 \x01(\x0b\x32\x1c.mgmt.v1alpha1.JobHookConfigR\x06\x63onfig\x12\x18\n\x07\x65nabled\x18\x05 \x01(\x08R\x07\x65nabled\x12%\n\x08priority\x18\x06 \x01(\rB\t\xbaH\x06*\x04\x18\x64(\x00R\x08priority\"C\n\x15UpdateJobHookResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"N\n\x18SetJobHookEnabledRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x18\n\x07\x65nabled\x18\x02 \x01(\x08R\x07\x65nabled\"G\n\x19SetJobHookEnabledResponse\x12*\n\x04hook\x18\x01 \x01(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x04hook\"\xde\x01\n GetActiveJobHooksByTimingRequest\x12\x1f\n\x06job_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x05jobId\x12N\n\x06timing\x18\x02 \x01(\x0e\x32\x36.mgmt.v1alpha1.GetActiveJobHooksByTimingRequest.TimingR\x06timing\"I\n\x06Timing\x12\x16\n\x12TIMING_UNSPECIFIED\x10\x00\x12\x12\n\x0eTIMING_PRESYNC\x10\x01\x12\x13\n\x0fTIMING_POSTSYNC\x10\x02\"Q\n!GetActiveJobHooksByTimingResponse\x12,\n\x05hooks\x18\x01 \x03(\x0b\x32\x16.mgmt.v1alpha1.JobHookR\x05hooks*o\n\tJobStatus\x12\x1a\n\x16JOB_STATUS_UNSPECIFIED\x10\x00\x12\x16\n\x12JOB_STATUS_ENABLED\x10\x01\x12\x15\n\x11JOB_STATUS_PAUSED\x10\x03\x12\x17\n\x13JOB_STATUS_DISABLED\x10\x04*\xa7\x01\n\x0e\x41\x63tivityStatus\x12\x1f\n\x1b\x41\x43TIVITY_STATUS_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x41\x43TIVITY_STATUS_SCHEDULED\x10\x01\x12\x1b\n\x17\x41\x43TIVITY_STATUS_STARTED\x10\x02\x12\x1c\n\x18\x41\x43TIVITY_STATUS_CANCELED\x10\x03\x12\x1a\n\x16\x41\x43TIVITY_STATUS_FAILED\x10\x04*\x92\x02\n\x0cJobRunStatus\x12\x1e\n\x1aJOB_RUN_STATUS_UNSPECIFIED\x10\x00\x12\x1a\n\x16JOB_RUN_STATUS_PENDING\x10\x01\x12\x1a\n\x16JOB_RUN_STATUS_RUNNING\x10\x02\x12\x1b\n\x17JOB_RUN_STATUS_COMPLETE\x10\x03\x12\x18\n\x14JOB_RUN_STATUS_ERROR\x10\x04\x12\x1b\n\x17JOB_RUN_STATUS_CANCELED\x10\x05\x12\x1d\n\x19JOB_RUN_STATUS_TERMINATED\x10\x06\x12\x19\n\x15JOB_RUN_STATUS_FAILED\x10\x07\x12\x1c\n\x18JOB_RUN_STATUS_TIMED_OUT\x10\x08*|\n\tLogWindow\x12\"\n\x1eLOG_WINDOW_NO_TIME_UNSPECIFIED\x10\x00\x12\x1a\n\x16LOG_WINDOW_FIFTEEN_MIN\x10\x01\x12\x17\n\x13LOG_WINDOW_ONE_HOUR\x10\x02\x12\x16\n\x12LOG_WINDOW_ONE_DAY\x10\x03*w\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x01\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x02\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x03\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x04\x32\xd6\x1f\n\nJobService\x12M\n\x07GetJobs\x12\x1d.mgmt.v1alpha1.GetJobsRequest\x1a\x1e.mgmt.v1alpha1.GetJobsResponse\"\x03\x90\x02\x01\x12J\n\x06GetJob\x12\x1c.mgmt.v1alpha1.GetJobRequest\x1a\x1d.mgmt.v1alpha1.GetJobResponse\"\x03\x90\x02\x01\x12P\n\tCreateJob\x12\x1f.mgmt.v1alpha1.CreateJobRequest\x1a .mgmt.v1alpha1.CreateJobResponse\"\x00\x12P\n\tDeleteJob\x12\x1f.mgmt.v1alpha1.DeleteJobRequest\x1a .mgmt.v1alpha1.DeleteJobResponse\"\x00\x12n\n\x12IsJobNameAvailable\x12(.mgmt.v1alpha1.IsJobNameAvailableRequest\x1a).mgmt.v1alpha1.IsJobNameAvailableResponse\"\x03\x90\x02\x01\x12h\n\x11UpdateJobSchedule\x12\'.mgmt.v1alpha1.UpdateJobScheduleRequest\x1a(.mgmt.v1alpha1.UpdateJobScheduleResponse\"\x00\x12\x80\x01\n\x19UpdateJobSourceConnection\x12/.mgmt.v1alpha1.UpdateJobSourceConnectionRequest\x1a\x30.mgmt.v1alpha1.UpdateJobSourceConnectionResponse\"\x00\x12\x95\x01\n SetJobSourceSqlConnectionSubsets\x12\x36.mgmt.v1alpha1.SetJobSourceSqlConnectionSubsetsRequest\x1a\x37.mgmt.v1alpha1.SetJobSourceSqlConnectionSubsetsResponse\"\x00\x12\x8f\x01\n\x1eUpdateJobDestinationConnection\x12\x34.mgmt.v1alpha1.UpdateJobDestinationConnectionRequest\x1a\x35.mgmt.v1alpha1.UpdateJobDestinationConnectionResponse\"\x00\x12\x8f\x01\n\x1e\x44\x65leteJobDestinationConnection\x12\x34.mgmt.v1alpha1.DeleteJobDestinationConnectionRequest\x1a\x35.mgmt.v1alpha1.DeleteJobDestinationConnectionResponse\"\x00\x12\x92\x01\n\x1f\x43reateJobDestinationConnections\x12\x35.mgmt.v1alpha1.CreateJobDestinationConnectionsRequest\x1a\x36.mgmt.v1alpha1.CreateJobDestinationConnectionsResponse\"\x00\x12M\n\x08PauseJob\x12\x1e.mgmt.v1alpha1.PauseJobRequest\x1a\x1f.mgmt.v1alpha1.PauseJobResponse\"\x00\x12h\n\x10GetJobRecentRuns\x12&.mgmt.v1alpha1.GetJobRecentRunsRequest\x1a\'.mgmt.v1alpha1.GetJobRecentRunsResponse\"\x03\x90\x02\x01\x12\x62\n\x0eGetJobNextRuns\x12$.mgmt.v1alpha1.GetJobNextRunsRequest\x1a%.mgmt.v1alpha1.GetJobNextRunsResponse\"\x03\x90\x02\x01\x12\\\n\x0cGetJobStatus\x12\".mgmt.v1alpha1.GetJobStatusRequest\x1a#.mgmt.v1alpha1.GetJobStatusResponse\"\x03\x90\x02\x01\x12\x62\n\x0eGetJobStatuses\x12$.mgmt.v1alpha1.GetJobStatusesRequest\x1a%.mgmt.v1alpha1.GetJobStatusesResponse\"\x03\x90\x02\x01\x12V\n\nGetJobRuns\x12 .mgmt.v1alpha1.GetJobRunsRequest\x1a!.mgmt.v1alpha1.GetJobRunsResponse\"\x03\x90\x02\x01\x12\x65\n\x0fGetJobRunEvents\x12%.mgmt.v1alpha1.GetJobRunEventsRequest\x1a&.mgmt.v1alpha1.GetJobRunEventsResponse\"\x03\x90\x02\x01\x12S\n\tGetJobRun\x12\x1f.mgmt.v1alpha1.GetJobRunRequest\x1a .mgmt.v1alpha1.GetJobRunResponse\"\x03\x90\x02\x01\x12Y\n\x0c\x44\x65leteJobRun\x12\".mgmt.v1alpha1.DeleteJobRunRequest\x1a#.mgmt.v1alpha1.DeleteJobRunResponse\"\x00\x12Y\n\x0c\x43reateJobRun\x12\".mgmt.v1alpha1.CreateJobRunRequest\x1a#.mgmt.v1alpha1.CreateJobRunResponse\"\x00\x12Y\n\x0c\x43\x61ncelJobRun\x12\".mgmt.v1alpha1.CancelJobRunRequest\x1a#.mgmt.v1alpha1.CancelJobRunResponse\"\x00\x12\x62\n\x0fTerminateJobRun\x12%.mgmt.v1alpha1.TerminateJobRunRequest\x1a&.mgmt.v1alpha1.TerminateJobRunResponse\"\x00\x12p\n\x13GetJobRunLogsStream\x12).mgmt.v1alpha1.GetJobRunLogsStreamRequest\x1a*.mgmt.v1alpha1.GetJobRunLogsStreamResponse\"\x00\x30\x01\x12\\\n\rGetJobRunLogs\x12#.mgmt.v1alpha1.GetJobRunLogsRequest\x1a$.mgmt.v1alpha1.GetJobRunLogsResponse\"\x00\x12t\n\x15SetJobWorkflowOptions\x12+.mgmt.v1alpha1.SetJobWorkflowOptionsRequest\x1a,.mgmt.v1alpha1.SetJobWorkflowOptionsResponse\"\x00\x12h\n\x11SetJobSyncOptions\x12\'.mgmt.v1alpha1.SetJobSyncOptionsRequest\x1a(.mgmt.v1alpha1.SetJobSyncOptionsResponse\"\x00\x12n\n\x13ValidateJobMappings\x12).mgmt.v1alpha1.ValidateJobMappingsRequest\x1a*.mgmt.v1alpha1.ValidateJobMappingsResponse\"\x00\x12\\\n\rGetRunContext\x12#.mgmt.v1alpha1.GetRunContextRequest\x1a$.mgmt.v1alpha1.GetRunContextResponse\"\x00\x12\\\n\rSetRunContext\x12#.mgmt.v1alpha1.SetRunContextRequest\x1a$.mgmt.v1alpha1.SetRunContextResponse\"\x00\x12\x61\n\x0eSetRunContexts\x12$.mgmt.v1alpha1.SetRunContextsRequest\x1a%.mgmt.v1alpha1.SetRunContextsResponse\"\x00(\x01\x12Y\n\x0bGetJobHooks\x12!.mgmt.v1alpha1.GetJobHooksRequest\x1a\".mgmt.v1alpha1.GetJobHooksResponse\"\x03\x90\x02\x01\x12V\n\nGetJobHook\x12 .mgmt.v1alpha1.GetJobHookRequest\x1a!.mgmt.v1alpha1.GetJobHookResponse\"\x03\x90\x02\x01\x12\\\n\rCreateJobHook\x12#.mgmt.v1alpha1.CreateJobHookRequest\x1a$.mgmt.v1alpha1.CreateJobHookResponse\"\x00\x12\\\n\rDeleteJobHook\x12#.mgmt.v1alpha1.DeleteJobHookRequest\x1a$.mgmt.v1alpha1.DeleteJobHookResponse\"\x00\x12w\n\x16IsJobHookNameAvailable\x12,.mgmt.v1alpha1.IsJobHookNameAvailableRequest\x1a-.mgmt.v1alpha1.IsJobHookNameAvailableResponse\"\x00\x12\\\n\rUpdateJobHook\x12#.mgmt.v1alpha1.UpdateJobHookRequest\x1a$.mgmt.v1alpha1.UpdateJobHookResponse\"\x00\x12h\n\x11SetJobHookEnabled\x12\'.mgmt.v1alpha1.SetJobHookEnabledRequest\x1a(.mgmt.v1alpha1.SetJobHookEnabledResponse\"\x00\x12\x83\x01\n\x19GetActiveJobHooksByTiming\x12/.mgmt.v1alpha1.GetActiveJobHooksByTimingRequest\x1a\x30.mgmt.v1alpha1.GetActiveJobHooksByTimingResponse\"\x03\x90\x02\x01\x42\xc4\x01\n\x11\x63om.mgmt.v1alpha1B\x08JobProtoP\x01ZPgithub.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1;mgmtv1alpha1\xa2\x02\x03MXX\xaa\x02\rMgmt.V1alpha1\xca\x02\rMgmt\\V1alpha1\xe2\x02\x19Mgmt\\V1alpha1\\GPBMetadata\xea\x02\x0eMgmt::V1alpha1b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -195,6 +195,10 @@
_globals['_GETJOBRUNLOGSSTREAMREQUEST'].fields_by_name['account_id']._serialized_options = b'\272H\005r\003\260\001\001'
_globals['_GETJOBRUNLOGSSTREAMREQUEST'].fields_by_name['max_log_lines']._loaded_options = None
_globals['_GETJOBRUNLOGSSTREAMREQUEST'].fields_by_name['max_log_lines']._serialized_options = b'\272H\004\"\002(\001'
+ _globals['_GETJOBRUNLOGSREQUEST'].fields_by_name['account_id']._loaded_options = None
+ _globals['_GETJOBRUNLOGSREQUEST'].fields_by_name['account_id']._serialized_options = b'\272H\005r\003\260\001\001'
+ _globals['_GETJOBRUNLOGSREQUEST'].fields_by_name['max_log_lines']._loaded_options = None
+ _globals['_GETJOBRUNLOGSREQUEST'].fields_by_name['max_log_lines']._serialized_options = b'\272H\004\"\002(\001'
_globals['_SETJOBWORKFLOWOPTIONSREQUEST'].fields_by_name['id']._loaded_options = None
_globals['_SETJOBWORKFLOWOPTIONSREQUEST'].fields_by_name['id']._serialized_options = b'\272H\005r\003\260\001\001'
_globals['_SETJOBSYNCOPTIONSREQUEST'].fields_by_name['id']._loaded_options = None
@@ -269,16 +273,16 @@
_globals['_JOBSERVICE'].methods_by_name['GetJobHook']._serialized_options = b'\220\002\001'
_globals['_JOBSERVICE'].methods_by_name['GetActiveJobHooksByTiming']._loaded_options = None
_globals['_JOBSERVICE'].methods_by_name['GetActiveJobHooksByTiming']._serialized_options = b'\220\002\001'
- _globals['_JOBSTATUS']._serialized_start=23522
- _globals['_JOBSTATUS']._serialized_end=23633
- _globals['_ACTIVITYSTATUS']._serialized_start=23636
- _globals['_ACTIVITYSTATUS']._serialized_end=23803
- _globals['_JOBRUNSTATUS']._serialized_start=23806
- _globals['_JOBRUNSTATUS']._serialized_end=24080
- _globals['_LOGWINDOW']._serialized_start=24082
- _globals['_LOGWINDOW']._serialized_end=24206
- _globals['_LOGLEVEL']._serialized_start=24208
- _globals['_LOGLEVEL']._serialized_end=24327
+ _globals['_JOBSTATUS']._serialized_start=24008
+ _globals['_JOBSTATUS']._serialized_end=24119
+ _globals['_ACTIVITYSTATUS']._serialized_start=24122
+ _globals['_ACTIVITYSTATUS']._serialized_end=24289
+ _globals['_JOBRUNSTATUS']._serialized_start=24292
+ _globals['_JOBRUNSTATUS']._serialized_end=24566
+ _globals['_LOGWINDOW']._serialized_start=24568
+ _globals['_LOGWINDOW']._serialized_end=24692
+ _globals['_LOGLEVEL']._serialized_start=24694
+ _globals['_LOGLEVEL']._serialized_end=24813
_globals['_GETJOBSREQUEST']._serialized_start=137
_globals['_GETJOBSREQUEST']._serialized_end=194
_globals['_GETJOBSRESPONSE']._serialized_start=196
@@ -533,90 +537,96 @@
_globals['_GETJOBRUNLOGSSTREAMREQUEST']._serialized_end=18829
_globals['_GETJOBRUNLOGSSTREAMRESPONSE']._serialized_start=18832
_globals['_GETJOBRUNLOGSSTREAMRESPONSE']._serialized_end=18965
- _globals['_SETJOBWORKFLOWOPTIONSREQUEST']._serialized_start=18968
- _globals['_SETJOBWORKFLOWOPTIONSREQUEST']._serialized_end=19099
- _globals['_SETJOBWORKFLOWOPTIONSRESPONSE']._serialized_start=19101
- _globals['_SETJOBWORKFLOWOPTIONSRESPONSE']._serialized_end=19170
- _globals['_SETJOBSYNCOPTIONSREQUEST']._serialized_start=19172
- _globals['_SETJOBSYNCOPTIONSREQUEST']._serialized_end=19291
- _globals['_SETJOBSYNCOPTIONSRESPONSE']._serialized_start=19293
- _globals['_SETJOBSYNCOPTIONSRESPONSE']._serialized_end=19358
- _globals['_VALIDATEJOBMAPPINGSREQUEST']._serialized_start=19361
- _globals['_VALIDATEJOBMAPPINGSREQUEST']._serialized_end=19700
- _globals['_COLUMNERROR']._serialized_start=19702
- _globals['_COLUMNERROR']._serialized_end=19809
- _globals['_COLUMNWARNING']._serialized_start=19811
- _globals['_COLUMNWARNING']._serialized_end=19924
- _globals['_DATABASEERROR']._serialized_start=19926
- _globals['_DATABASEERROR']._serialized_end=19965
- _globals['_VALIDATEJOBMAPPINGSRESPONSE']._serialized_start=19968
- _globals['_VALIDATEJOBMAPPINGSRESPONSE']._serialized_end=20204
- _globals['_VIRTUALFOREIGNKEY']._serialized_start=20206
- _globals['_VIRTUALFOREIGNKEY']._serialized_end=20297
- _globals['_VIRTUALFOREIGNCONSTRAINT']._serialized_start=20300
- _globals['_VIRTUALFOREIGNCONSTRAINT']._serialized_end=20465
- _globals['_RUNCONTEXTKEY']._serialized_start=20468
- _globals['_RUNCONTEXTKEY']._serialized_end=20604
- _globals['_GETRUNCONTEXTREQUEST']._serialized_start=20606
- _globals['_GETRUNCONTEXTREQUEST']._serialized_end=20674
- _globals['_GETRUNCONTEXTRESPONSE']._serialized_start=20676
- _globals['_GETRUNCONTEXTRESPONSE']._serialized_end=20721
- _globals['_SETRUNCONTEXTREQUEST']._serialized_start=20723
- _globals['_SETRUNCONTEXTREQUEST']._serialized_end=20813
- _globals['_SETRUNCONTEXTRESPONSE']._serialized_start=20815
- _globals['_SETRUNCONTEXTRESPONSE']._serialized_end=20838
- _globals['_SETRUNCONTEXTSREQUEST']._serialized_start=20840
- _globals['_SETRUNCONTEXTSREQUEST']._serialized_end=20931
- _globals['_SETRUNCONTEXTSRESPONSE']._serialized_start=20933
- _globals['_SETRUNCONTEXTSRESPONSE']._serialized_end=20957
- _globals['_JOBHOOK']._serialized_start=20960
- _globals['_JOBHOOK']._serialized_end=21389
- _globals['_NEWJOBHOOK']._serialized_start=21392
- _globals['_NEWJOBHOOK']._serialized_end=21613
- _globals['_JOBHOOKCONFIG']._serialized_start=21616
- _globals['_JOBHOOKCONFIG']._serialized_end=22061
- _globals['_JOBHOOKCONFIG_JOBSQLHOOK']._serialized_start=21695
- _globals['_JOBHOOKCONFIG_JOBSQLHOOK']._serialized_end=22020
- _globals['_JOBHOOKCONFIG_JOBSQLHOOK_TIMING']._serialized_start=21860
- _globals['_JOBHOOKCONFIG_JOBSQLHOOK_TIMING']._serialized_end=22020
- _globals['_JOBHOOKTIMINGPRESYNC']._serialized_start=22063
- _globals['_JOBHOOKTIMINGPRESYNC']._serialized_end=22085
- _globals['_JOBHOOKTIMINGPOSTSYNC']._serialized_start=22087
- _globals['_JOBHOOKTIMINGPOSTSYNC']._serialized_end=22110
- _globals['_GETJOBHOOKSREQUEST']._serialized_start=22112
- _globals['_GETJOBHOOKSREQUEST']._serialized_end=22165
- _globals['_GETJOBHOOKSRESPONSE']._serialized_start=22167
- _globals['_GETJOBHOOKSRESPONSE']._serialized_end=22234
- _globals['_GETJOBHOOKREQUEST']._serialized_start=22236
- _globals['_GETJOBHOOKREQUEST']._serialized_end=22281
- _globals['_GETJOBHOOKRESPONSE']._serialized_start=22283
- _globals['_GETJOBHOOKRESPONSE']._serialized_end=22347
- _globals['_CREATEJOBHOOKREQUEST']._serialized_start=22349
- _globals['_CREATEJOBHOOKREQUEST']._serialized_end=22441
- _globals['_CREATEJOBHOOKRESPONSE']._serialized_start=22443
- _globals['_CREATEJOBHOOKRESPONSE']._serialized_end=22510
- _globals['_DELETEJOBHOOKREQUEST']._serialized_start=22512
- _globals['_DELETEJOBHOOKREQUEST']._serialized_end=22560
- _globals['_DELETEJOBHOOKRESPONSE']._serialized_start=22562
- _globals['_DELETEJOBHOOKRESPONSE']._serialized_end=22585
- _globals['_ISJOBHOOKNAMEAVAILABLEREQUEST']._serialized_start=22587
- _globals['_ISJOBHOOKNAMEAVAILABLEREQUEST']._serialized_end=22661
- _globals['_ISJOBHOOKNAMEAVAILABLERESPONSE']._serialized_start=22663
- _globals['_ISJOBHOOKNAMEAVAILABLERESPONSE']._serialized_end=22730
- _globals['_UPDATEJOBHOOKREQUEST']._serialized_start=22733
- _globals['_UPDATEJOBHOOKREQUEST']._serialized_end=22990
- _globals['_UPDATEJOBHOOKRESPONSE']._serialized_start=22992
- _globals['_UPDATEJOBHOOKRESPONSE']._serialized_end=23059
- _globals['_SETJOBHOOKENABLEDREQUEST']._serialized_start=23061
- _globals['_SETJOBHOOKENABLEDREQUEST']._serialized_end=23139
- _globals['_SETJOBHOOKENABLEDRESPONSE']._serialized_start=23141
- _globals['_SETJOBHOOKENABLEDRESPONSE']._serialized_end=23212
- _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST']._serialized_start=23215
- _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST']._serialized_end=23437
- _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST_TIMING']._serialized_start=23364
- _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST_TIMING']._serialized_end=23437
- _globals['_GETACTIVEJOBHOOKSBYTIMINGRESPONSE']._serialized_start=23439
- _globals['_GETACTIVEJOBHOOKSBYTIMINGRESPONSE']._serialized_end=23520
- _globals['_JOBSERVICE']._serialized_start=24330
- _globals['_JOBSERVICE']._serialized_end=28290
+ _globals['_GETJOBRUNLOGSREQUEST']._serialized_start=18968
+ _globals['_GETJOBRUNLOGSREQUEST']._serialized_end=19235
+ _globals['_GETJOBRUNLOGSRESPONSE']._serialized_start=19238
+ _globals['_GETJOBRUNLOGSRESPONSE']._serialized_end=19451
+ _globals['_GETJOBRUNLOGSRESPONSE_LOGLINE']._serialized_start=19338
+ _globals['_GETJOBRUNLOGSRESPONSE_LOGLINE']._serialized_end=19451
+ _globals['_SETJOBWORKFLOWOPTIONSREQUEST']._serialized_start=19454
+ _globals['_SETJOBWORKFLOWOPTIONSREQUEST']._serialized_end=19585
+ _globals['_SETJOBWORKFLOWOPTIONSRESPONSE']._serialized_start=19587
+ _globals['_SETJOBWORKFLOWOPTIONSRESPONSE']._serialized_end=19656
+ _globals['_SETJOBSYNCOPTIONSREQUEST']._serialized_start=19658
+ _globals['_SETJOBSYNCOPTIONSREQUEST']._serialized_end=19777
+ _globals['_SETJOBSYNCOPTIONSRESPONSE']._serialized_start=19779
+ _globals['_SETJOBSYNCOPTIONSRESPONSE']._serialized_end=19844
+ _globals['_VALIDATEJOBMAPPINGSREQUEST']._serialized_start=19847
+ _globals['_VALIDATEJOBMAPPINGSREQUEST']._serialized_end=20186
+ _globals['_COLUMNERROR']._serialized_start=20188
+ _globals['_COLUMNERROR']._serialized_end=20295
+ _globals['_COLUMNWARNING']._serialized_start=20297
+ _globals['_COLUMNWARNING']._serialized_end=20410
+ _globals['_DATABASEERROR']._serialized_start=20412
+ _globals['_DATABASEERROR']._serialized_end=20451
+ _globals['_VALIDATEJOBMAPPINGSRESPONSE']._serialized_start=20454
+ _globals['_VALIDATEJOBMAPPINGSRESPONSE']._serialized_end=20690
+ _globals['_VIRTUALFOREIGNKEY']._serialized_start=20692
+ _globals['_VIRTUALFOREIGNKEY']._serialized_end=20783
+ _globals['_VIRTUALFOREIGNCONSTRAINT']._serialized_start=20786
+ _globals['_VIRTUALFOREIGNCONSTRAINT']._serialized_end=20951
+ _globals['_RUNCONTEXTKEY']._serialized_start=20954
+ _globals['_RUNCONTEXTKEY']._serialized_end=21090
+ _globals['_GETRUNCONTEXTREQUEST']._serialized_start=21092
+ _globals['_GETRUNCONTEXTREQUEST']._serialized_end=21160
+ _globals['_GETRUNCONTEXTRESPONSE']._serialized_start=21162
+ _globals['_GETRUNCONTEXTRESPONSE']._serialized_end=21207
+ _globals['_SETRUNCONTEXTREQUEST']._serialized_start=21209
+ _globals['_SETRUNCONTEXTREQUEST']._serialized_end=21299
+ _globals['_SETRUNCONTEXTRESPONSE']._serialized_start=21301
+ _globals['_SETRUNCONTEXTRESPONSE']._serialized_end=21324
+ _globals['_SETRUNCONTEXTSREQUEST']._serialized_start=21326
+ _globals['_SETRUNCONTEXTSREQUEST']._serialized_end=21417
+ _globals['_SETRUNCONTEXTSRESPONSE']._serialized_start=21419
+ _globals['_SETRUNCONTEXTSRESPONSE']._serialized_end=21443
+ _globals['_JOBHOOK']._serialized_start=21446
+ _globals['_JOBHOOK']._serialized_end=21875
+ _globals['_NEWJOBHOOK']._serialized_start=21878
+ _globals['_NEWJOBHOOK']._serialized_end=22099
+ _globals['_JOBHOOKCONFIG']._serialized_start=22102
+ _globals['_JOBHOOKCONFIG']._serialized_end=22547
+ _globals['_JOBHOOKCONFIG_JOBSQLHOOK']._serialized_start=22181
+ _globals['_JOBHOOKCONFIG_JOBSQLHOOK']._serialized_end=22506
+ _globals['_JOBHOOKCONFIG_JOBSQLHOOK_TIMING']._serialized_start=22346
+ _globals['_JOBHOOKCONFIG_JOBSQLHOOK_TIMING']._serialized_end=22506
+ _globals['_JOBHOOKTIMINGPRESYNC']._serialized_start=22549
+ _globals['_JOBHOOKTIMINGPRESYNC']._serialized_end=22571
+ _globals['_JOBHOOKTIMINGPOSTSYNC']._serialized_start=22573
+ _globals['_JOBHOOKTIMINGPOSTSYNC']._serialized_end=22596
+ _globals['_GETJOBHOOKSREQUEST']._serialized_start=22598
+ _globals['_GETJOBHOOKSREQUEST']._serialized_end=22651
+ _globals['_GETJOBHOOKSRESPONSE']._serialized_start=22653
+ _globals['_GETJOBHOOKSRESPONSE']._serialized_end=22720
+ _globals['_GETJOBHOOKREQUEST']._serialized_start=22722
+ _globals['_GETJOBHOOKREQUEST']._serialized_end=22767
+ _globals['_GETJOBHOOKRESPONSE']._serialized_start=22769
+ _globals['_GETJOBHOOKRESPONSE']._serialized_end=22833
+ _globals['_CREATEJOBHOOKREQUEST']._serialized_start=22835
+ _globals['_CREATEJOBHOOKREQUEST']._serialized_end=22927
+ _globals['_CREATEJOBHOOKRESPONSE']._serialized_start=22929
+ _globals['_CREATEJOBHOOKRESPONSE']._serialized_end=22996
+ _globals['_DELETEJOBHOOKREQUEST']._serialized_start=22998
+ _globals['_DELETEJOBHOOKREQUEST']._serialized_end=23046
+ _globals['_DELETEJOBHOOKRESPONSE']._serialized_start=23048
+ _globals['_DELETEJOBHOOKRESPONSE']._serialized_end=23071
+ _globals['_ISJOBHOOKNAMEAVAILABLEREQUEST']._serialized_start=23073
+ _globals['_ISJOBHOOKNAMEAVAILABLEREQUEST']._serialized_end=23147
+ _globals['_ISJOBHOOKNAMEAVAILABLERESPONSE']._serialized_start=23149
+ _globals['_ISJOBHOOKNAMEAVAILABLERESPONSE']._serialized_end=23216
+ _globals['_UPDATEJOBHOOKREQUEST']._serialized_start=23219
+ _globals['_UPDATEJOBHOOKREQUEST']._serialized_end=23476
+ _globals['_UPDATEJOBHOOKRESPONSE']._serialized_start=23478
+ _globals['_UPDATEJOBHOOKRESPONSE']._serialized_end=23545
+ _globals['_SETJOBHOOKENABLEDREQUEST']._serialized_start=23547
+ _globals['_SETJOBHOOKENABLEDREQUEST']._serialized_end=23625
+ _globals['_SETJOBHOOKENABLEDRESPONSE']._serialized_start=23627
+ _globals['_SETJOBHOOKENABLEDRESPONSE']._serialized_end=23698
+ _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST']._serialized_start=23701
+ _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST']._serialized_end=23923
+ _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST_TIMING']._serialized_start=23850
+ _globals['_GETACTIVEJOBHOOKSBYTIMINGREQUEST_TIMING']._serialized_end=23923
+ _globals['_GETACTIVEJOBHOOKSBYTIMINGRESPONSE']._serialized_start=23925
+ _globals['_GETACTIVEJOBHOOKSBYTIMINGRESPONSE']._serialized_end=24006
+ _globals['_JOBSERVICE']._serialized_start=24816
+ _globals['_JOBSERVICE']._serialized_end=28870
# @@protoc_insertion_point(module_scope)
diff --git a/python/src/neosync/mgmt/v1alpha1/job_pb2.pyi b/python/src/neosync/mgmt/v1alpha1/job_pb2.pyi
index 6a8f862778..60a199adaa 100644
--- a/python/src/neosync/mgmt/v1alpha1/job_pb2.pyi
+++ b/python/src/neosync/mgmt/v1alpha1/job_pb2.pyi
@@ -1108,6 +1108,33 @@ class GetJobRunLogsStreamResponse(_message.Message):
timestamp: _timestamp_pb2.Timestamp
def __init__(self, log_line: _Optional[str] = ..., timestamp: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ...
+class GetJobRunLogsRequest(_message.Message):
+ __slots__ = ("job_run_id", "account_id", "window", "max_log_lines", "log_levels")
+ JOB_RUN_ID_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_ID_FIELD_NUMBER: _ClassVar[int]
+ WINDOW_FIELD_NUMBER: _ClassVar[int]
+ MAX_LOG_LINES_FIELD_NUMBER: _ClassVar[int]
+ LOG_LEVELS_FIELD_NUMBER: _ClassVar[int]
+ job_run_id: str
+ account_id: str
+ window: LogWindow
+ max_log_lines: int
+ log_levels: _containers.RepeatedScalarFieldContainer[LogLevel]
+ def __init__(self, job_run_id: _Optional[str] = ..., account_id: _Optional[str] = ..., window: _Optional[_Union[LogWindow, str]] = ..., max_log_lines: _Optional[int] = ..., log_levels: _Optional[_Iterable[_Union[LogLevel, str]]] = ...) -> None: ...
+
+class GetJobRunLogsResponse(_message.Message):
+ __slots__ = ("log_lines",)
+ class LogLine(_message.Message):
+ __slots__ = ("log_line", "timestamp")
+ LOG_LINE_FIELD_NUMBER: _ClassVar[int]
+ TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+ log_line: str
+ timestamp: _timestamp_pb2.Timestamp
+ def __init__(self, log_line: _Optional[str] = ..., timestamp: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ...
+ LOG_LINES_FIELD_NUMBER: _ClassVar[int]
+ log_lines: _containers.RepeatedCompositeFieldContainer[GetJobRunLogsResponse.LogLine]
+ def __init__(self, log_lines: _Optional[_Iterable[_Union[GetJobRunLogsResponse.LogLine, _Mapping]]] = ...) -> None: ...
+
class SetJobWorkflowOptionsRequest(_message.Message):
__slots__ = ("id", "worfklow_options")
ID_FIELD_NUMBER: _ClassVar[int]
diff --git a/python/src/neosync/mgmt/v1alpha1/job_pb2_grpc.py b/python/src/neosync/mgmt/v1alpha1/job_pb2_grpc.py
index 26202af89b..4c0ce45f66 100644
--- a/python/src/neosync/mgmt/v1alpha1/job_pb2_grpc.py
+++ b/python/src/neosync/mgmt/v1alpha1/job_pb2_grpc.py
@@ -135,6 +135,11 @@ def __init__(self, channel):
request_serializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsStreamRequest.SerializeToString,
response_deserializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsStreamResponse.FromString,
_registered_method=True)
+ self.GetJobRunLogs = channel.unary_unary(
+ '/mgmt.v1alpha1.JobService/GetJobRunLogs',
+ request_serializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsRequest.SerializeToString,
+ response_deserializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsResponse.FromString,
+ _registered_method=True)
self.SetJobWorkflowOptions = channel.unary_unary(
'/mgmt.v1alpha1.JobService/SetJobWorkflowOptions',
request_serializer=mgmt_dot_v1alpha1_dot_job__pb2.SetJobWorkflowOptionsRequest.SerializeToString,
@@ -379,6 +384,14 @@ def GetJobRunLogsStream(self, request, context):
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
+ def GetJobRunLogs(self, request, context):
+ """Returns a list of logs from the worker nodes that pertain to a specific job run.
+ Equivalent to the stream endpoint, but runs in a unary fashion.
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
def SetJobWorkflowOptions(self, request, context):
"""Set any job workflow options. Must provide entire object as is it will fully override the previous configuration
"""
@@ -600,6 +613,11 @@ def add_JobServiceServicer_to_server(servicer, server):
request_deserializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsStreamRequest.FromString,
response_serializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsStreamResponse.SerializeToString,
),
+ 'GetJobRunLogs': grpc.unary_unary_rpc_method_handler(
+ servicer.GetJobRunLogs,
+ request_deserializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsRequest.FromString,
+ response_serializer=mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsResponse.SerializeToString,
+ ),
'SetJobWorkflowOptions': grpc.unary_unary_rpc_method_handler(
servicer.SetJobWorkflowOptions,
request_deserializer=mgmt_dot_v1alpha1_dot_job__pb2.SetJobWorkflowOptionsRequest.FromString,
@@ -1330,6 +1348,33 @@ def GetJobRunLogsStream(request,
metadata,
_registered_method=True)
+ @staticmethod
+ def GetJobRunLogs(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/mgmt.v1alpha1.JobService/GetJobRunLogs',
+ mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsRequest.SerializeToString,
+ mgmt_dot_v1alpha1_dot_job__pb2.GetJobRunLogsResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
@staticmethod
def SetJobWorkflowOptions(request,
target,
diff --git a/tools/generators/neosync_transformer_generator/main.go b/tools/generators/neosync_transformer_generator/main.go
index edebf455f0..1bf3b70c4b 100644
--- a/tools/generators/neosync_transformer_generator/main.go
+++ b/tools/generators/neosync_transformer_generator/main.go
@@ -3,12 +3,8 @@ package main
import (
"bytes"
"fmt"
- "go/parser"
"go/token"
- "io/fs"
- "log"
"os"
- "path/filepath"
"strings"
"text/template"
@@ -23,37 +19,11 @@ func main() {
packageName := args[1]
fileSet := token.NewFileSet()
- transformerFuncs := []*transformers.BenthosSpec{}
-
- err := filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
- if !d.IsDir() && filepath.Ext(path) == ".go" {
- node, err := parser.ParseFile(fileSet, path, nil, parser.ParseComments)
- if err != nil {
- log.Printf("Failed to parse file %s: %v", path, err)
- return nil
- }
- for _, cgroup := range node.Comments {
- for _, comment := range cgroup.List {
- if strings.HasPrefix(comment.Text, "// +neosyncTransformerBuilder:") {
- parts := strings.Split(comment.Text, ":")
- if len(parts) < 3 {
- continue
- }
- transformerFuncs = append(transformerFuncs, &transformers.BenthosSpec{
- SourceFile: path,
- Name: parts[2],
- Type: parts[1],
- Description: "",
- Example: "",
- })
- }
- }
- }
- }
- return nil
- })
+
+ transformerFuncs, err := transformers.ExtractBenthosSpec(fileSet)
if err != nil {
- log.Fatalf("impossible to walk directories: %s", err)
+ fmt.Println("Error finding transformer bloblang specs:", err) //nolint:forbidigo
+ return
}
for _, tf := range transformerFuncs {
@@ -64,6 +34,7 @@ func main() {
tf.Params = p.Params
tf.Description = p.SpecDescription
tf.BloblangFuncName = p.BloblangFuncName
+ tf.Category = p.Category
}
for _, tf := range transformerFuncs {
@@ -86,6 +57,25 @@ func main() {
}
outputFile.Close()
}
+
+ // generate transformer benchmarks
+ benchmarkCode, err := generateBenchmarkCode(packageName, transformerFuncs)
+ if err != nil {
+ fmt.Println("Error generating benchmarks:", err)
+ return
+ }
+ outputFile, err := os.Create("benchmarks_test.go")
+ if err != nil {
+ fmt.Println("Error creating benchmarks file:", err)
+ return
+ }
+
+ _, err = outputFile.WriteString(benchmarkCode)
+ if err != nil {
+ fmt.Println("Error writing to benchmarks file:", err)
+ return
+ }
+ outputFile.Close()
}
const codeTemplate = `
@@ -300,8 +290,100 @@ func generateCode(pkgName string, funcInfo *transformers.BenthosSpec) (string, e
}
func capitalizeFirst(s string) string {
- if len(s) == 0 {
+ if s == "" {
return s
}
return strings.ToUpper(string(s[0])) + s[1:]
}
+
+var testValues = map[string]any{
+ "string": `"test"`,
+ "int64": 123456,
+ "float64": 123.45,
+ "boolean": true,
+ "email": `"test@test.com"`,
+}
+
+const benchmarkTemplate = `
+// Code generated by Neosync neosync_transformer_generator.go. DO NOT EDIT.
+
+package {{.PackageName}}
+
+import (
+ "testing"
+)
+{{ $testValues := .TestValues }}
+{{- range $index, $spec := .TransformerSpecs }}
+{{- if eq $spec.Type "generate" }}
+func Benchmark{{$spec.Name}}(b *testing.B) {
+ generator := New{{$spec.Name}}()
+ opts, err := New{{$spec.Name}}Opts(
+ {{- range $index, $param := $spec.Params }}
+ {{- if eq $param.Name "value" }}{{ continue }}{{ end -}}
+ nil,
+ {{- end -}}
+ )
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+{{- end }}
+
+{{ if eq $spec.Type "transform" }}
+func Benchmark{{$spec.Name}}(b *testing.B) {
+ transformer := New{{$spec.Name}}()
+ opts, err := New{{$spec.Name}}Opts(
+ {{- range $index, $param := $spec.Params }}
+ {{- if eq $param.Name "value" }}{{ continue }}{{ end -}}
+ nil,
+ {{- end -}}
+ )
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform({{index $testValues $spec.Category}}, opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+{{- end }}
+{{- end }}
+`
+
+type BenchmarkTemplateData struct {
+ // SourceFile string
+ TestValues map[string]any
+ PackageName string
+ TransformerSpecs []*transformers.BenthosSpec
+ StructName string
+}
+
+func generateBenchmarkCode(pkgName string, transformerSpecs []*transformers.BenthosSpec) (string, error) {
+ for _, tf := range transformerSpecs {
+ tf.Name = capitalizeFirst(tf.Name)
+ }
+
+ data := BenchmarkTemplateData{
+ PackageName: pkgName,
+ TransformerSpecs: transformerSpecs,
+ TestValues: testValues,
+ }
+
+ t := template.Must(template.New("neosyncTransformerBenchmarkImpl").Parse(benchmarkTemplate))
+ var out bytes.Buffer
+ err := t.Execute(&out, data)
+ if err != nil {
+ return "", err
+ }
+ return out.String(), nil
+}
diff --git a/tools/go.mod b/tools/go.mod
index 498430a6ba..2e4bc4ce8f 100644
--- a/tools/go.mod
+++ b/tools/go.mod
@@ -15,7 +15,6 @@ require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1 // indirect
github.com/Jeffail/gabs/v2 v2.7.0 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
- github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/go-logr/logr v1.4.2 // indirect
@@ -25,7 +24,6 @@ require (
github.com/gorilla/css v1.0.1 // indirect
github.com/matoous/go-nanoid/v2 v2.0.0 // indirect
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
- github.com/oapi-codegen/runtime v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/stretchr/objx v0.5.2 // indirect
diff --git a/tools/go.sum b/tools/go.sum
index 9ba237473c..159a3ca98b 100644
--- a/tools/go.sum
+++ b/tools/go.sum
@@ -4,51 +4,27 @@ connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
cuelang.org/go v0.7.1 h1:wSuUSIKR9M1yrph57l8EJATWVRWHaq/Zd0dFUL10PC8=
cuelang.org/go v0.7.1/go.mod h1:ix+3dM/bSpdG9xg6qpCgnJnpeLtciZu+O/rDbywoMII=
-dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
-dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
-github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
-github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Jeffail/gabs/v2 v2.7.0 h1:Y2edYaTcE8ZpRsR2AtmPu5xQdFDIthFG0jYhu5PY8kg=
github.com/Jeffail/gabs/v2 v2.7.0/go.mod h1:dp5ocw1FvBBQYssgHsG7I1WYsiLRtkUaB1FEtSwvNUw=
github.com/Jeffail/grok v1.1.0 h1:kiHmZ+0J5w/XUihRgU3DY9WIxKrNQCDjnfAb6bMLFaE=
github.com/Jeffail/grok v1.1.0/go.mod h1:dm0hLksrDwOMa6To7ORXCuLbuNtASIZTfYheavLpsuE=
github.com/Jeffail/shutdown v1.0.0 h1:afYjnY4pksqP/012m3NGJVccDI+WATdSzIMVHZKU8/Y=
github.com/Jeffail/shutdown v1.0.0/go.mod h1:5dT4Y1oe60SJELCkmAB1pr9uQyHBhh6cwDLQTfmuO5U=
-github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
-github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
-github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
-github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
-github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
-github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg=
github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
-github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
-github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
-github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
-github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
-github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
-github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4=
-github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
-github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
-github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
-github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
@@ -60,12 +36,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
-github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
-github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
-github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
@@ -98,7 +70,6 @@ github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/my
github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
-github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
@@ -107,8 +78,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
-github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U=
@@ -122,34 +91,12 @@ github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwX
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
-github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
-github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
-github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
-github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
-github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
-github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
-github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
-github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
-github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
-github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
-github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
-github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
-github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto=
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY=
-github.com/neilotoole/slogt v1.1.0 h1:c7qE92sq+V0yvCuaxph+RQ2jOKL61c4hqS1Bv9W7FZE=
-github.com/neilotoole/slogt v1.1.0/go.mod h1:RCrGXkPc/hYybNulqQrMHRtvlQ7F6NktNVLuLwk6V+w=
github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM=
github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8=
github.com/nucleuscloud/go-antlrv4-parser v0.0.0-20240830015744-041b46c70aa5 h1:MRc2C7I88nGhKbk1VRT3nnr6XtpClkHT35lhKbg6kD4=
github.com/nucleuscloud/go-antlrv4-parser v0.0.0-20240830015744-041b46c70aa5/go.mod h1:MtI3ufP40Bql/YkhZFvDcR9h479JKb+hEUElwweQMzo=
-github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
-github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
-github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
-github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
-github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pganalyze/pg_query_go/v5 v5.1.0 h1:MlxQqHZnvA3cbRQYyIrjxEjzo560P6MyTgtlaf3pmXg=
@@ -157,13 +104,9 @@ github.com/pganalyze/pg_query_go/v5 v5.1.0/go.mod h1:FsglvxidZsVN+Ltw3Ai6nTgPVcK
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
-github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/quipo/dependencysolver v0.0.0-20170801134659-2b009cb4ddcc h1:hK577yxEJ2f5s8w2iy2KimZmgrdAUZUNftE1ESmg2/Q=
github.com/quipo/dependencysolver v0.0.0-20170801134659-2b009cb4ddcc/go.mod h1:OQt6Zo5B3Zs+C49xul8kcHo+fZ1mCLPvd0LFxiZ2DHc=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
@@ -185,10 +128,6 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
-github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
-github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
-github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
-github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
@@ -201,7 +140,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
-github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
@@ -211,14 +149,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo=
-github.com/testcontainers/testcontainers-go v0.35.0/go.mod h1:oEVBj5zrfJTrgjwONs1SsRbnBtH9OKl+IGl3UMcr2B4=
github.com/tilinna/z85 v1.0.0 h1:uqFnJBlD01dosSeo5sK1G1YGbPuwqVHqR+12OJDRjUw=
github.com/tilinna/z85 v1.0.0/go.mod h1:EfpFU/DUY4ddEy6CRvk2l+UQNEzHbh+bqBQS+04Nkxs=
-github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
-github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
-github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
-github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/warpstreamlabs/bento v1.4.1 h1:DL+j+0iIqiIq4fPreSShPJWNPC7JbYj4x/RMr8rwPAg=
@@ -234,12 +166,8 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
-github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
-github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
diff --git a/worker/pkg/benthos/default_transform/processor.go b/worker/pkg/benthos/default_transform/processor.go
index b9ca6cfda9..ce0c48bd85 100644
--- a/worker/pkg/benthos/default_transform/processor.go
+++ b/worker/pkg/benthos/default_transform/processor.go
@@ -7,7 +7,7 @@ import (
"reflect"
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
- transformer "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
+ transformer_executor "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformer_executor"
"google.golang.org/protobuf/encoding/protojson"
@@ -45,7 +45,7 @@ func ReisterDefaultTransformerProcessor(env *service.Environment) error {
type defaultTransformerProcessor struct {
mappedKeys map[string]struct{}
- defaultTransformersInitMap map[primitiveType]*transformer.TransformerExecutor
+ defaultTransformersInitMap map[primitiveType]*transformer_executor.TransformerExecutor
logger *service.Logger
}
@@ -203,13 +203,13 @@ func (m *defaultTransformerProcessor) getValue(transformerKey primitiveType, val
return value, nil
}
-func initDefaultTransformers(defaultTransformerMap map[primitiveType]*mgmtv1alpha1.JobMappingTransformer) (map[primitiveType]*transformer.TransformerExecutor, error) {
- transformersInit := map[primitiveType]*transformer.TransformerExecutor{}
+func initDefaultTransformers(defaultTransformerMap map[primitiveType]*mgmtv1alpha1.JobMappingTransformer) (map[primitiveType]*transformer_executor.TransformerExecutor, error) {
+ transformersInit := map[primitiveType]*transformer_executor.TransformerExecutor{}
for k, t := range defaultTransformerMap {
if !shouldProcess(t) {
continue
}
- init, err := transformer.InitializeTransformer(t)
+ init, err := transformer_executor.InitializeTransformer(t)
if err != nil {
return nil, err
}
diff --git a/worker/pkg/benthos/default_transform/processor_test.go b/worker/pkg/benthos/default_transform/processor_test.go
index 28f66b13e7..04d6175bdb 100644
--- a/worker/pkg/benthos/default_transform/processor_test.go
+++ b/worker/pkg/benthos/default_transform/processor_test.go
@@ -3,7 +3,7 @@ package neosync_benthos_defaulttransform
import (
"testing"
- transformer "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
+ transformer_executor "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformer_executor"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -95,7 +95,7 @@ func Test_transformRoot(t *testing.T) {
func createMockProcessor(mappedKeys map[string]struct{}) *defaultTransformerProcessor {
return &defaultTransformerProcessor{
mappedKeys: mappedKeys,
- defaultTransformersInitMap: map[primitiveType]*transformer.TransformerExecutor{
+ defaultTransformersInitMap: map[primitiveType]*transformer_executor.TransformerExecutor{
String: {
Mutate: func(value any, opts any) (any, error) {
return "transformed_" + value.(string), nil
diff --git a/worker/pkg/benthos/environment/environment.go b/worker/pkg/benthos/environment/environment.go
index a451300262..c11d156d00 100644
--- a/worker/pkg/benthos/environment/environment.go
+++ b/worker/pkg/benthos/environment/environment.go
@@ -9,6 +9,7 @@ import (
neosync_benthos_defaulttransform "github.com/nucleuscloud/neosync/worker/pkg/benthos/default_transform"
neosync_benthos_dynamodb "github.com/nucleuscloud/neosync/worker/pkg/benthos/dynamodb"
neosync_benthos_error "github.com/nucleuscloud/neosync/worker/pkg/benthos/error"
+ javascript_processor "github.com/nucleuscloud/neosync/worker/pkg/benthos/javascript"
neosync_benthos_json "github.com/nucleuscloud/neosync/worker/pkg/benthos/json"
benthos_metrics "github.com/nucleuscloud/neosync/worker/pkg/benthos/metrics"
neosync_benthos_mongodb "github.com/nucleuscloud/neosync/worker/pkg/benthos/mongodb"
@@ -189,6 +190,11 @@ func NewWithEnvironment(env *service.Environment, logger *slog.Logger, opts ...O
return nil, fmt.Errorf("unable to register Neosync to MSSQL processor to benthos instance: %w", err)
}
+ err = javascript_processor.RegisterNeosyncJavascriptProcessor(env)
+ if err != nil {
+ return nil, fmt.Errorf("unable to register javascript processor to benthos instance: %w", err)
+ }
+
if config.blobEnv != nil {
env.UseBloblangEnvironment(config.blobEnv)
}
diff --git a/worker/pkg/benthos/javascript/benthos_value_api.go b/worker/pkg/benthos/javascript/benthos_value_api.go
new file mode 100644
index 0000000000..f06edabb56
--- /dev/null
+++ b/worker/pkg/benthos/javascript/benthos_value_api.go
@@ -0,0 +1,50 @@
+package javascript_processor
+
+import (
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+ "github.com/warpstreamlabs/bento/public/service"
+)
+
+// this is not thread safe
+type benthosValueApi struct {
+ message *service.Message
+}
+
+func newBatchBenthosValueApi() *benthosValueApi {
+ return &benthosValueApi{}
+}
+
+// used by batch processor to update the target message while being able to reuse the same VM
+func (b *benthosValueApi) SetMessage(message *service.Message) {
+ b.message = message
+}
+
+func (b *benthosValueApi) Message() *service.Message {
+ return b.message
+}
+
+var _ javascript_functions.ValueApi = (*benthosValueApi)(nil)
+
+func (b *benthosValueApi) SetBytes(bytes []byte) {
+ b.message.SetBytes(bytes)
+}
+
+func (b *benthosValueApi) AsBytes() ([]byte, error) {
+ return b.message.AsBytes()
+}
+
+func (b *benthosValueApi) SetStructured(value any) {
+ b.message.SetStructured(value)
+}
+
+func (b *benthosValueApi) AsStructured() (any, error) {
+ return b.message.AsStructured()
+}
+
+func (b *benthosValueApi) MetaGet(key string) (any, bool) {
+ return b.message.MetaGet(key)
+}
+
+func (b *benthosValueApi) MetaSetMut(key string, value any) {
+ b.message.MetaSetMut(key, value)
+}
diff --git a/worker/pkg/benthos/javascript/casts.go b/worker/pkg/benthos/javascript/casts.go
deleted file mode 100644
index 667f53f993..0000000000
--- a/worker/pkg/benthos/javascript/casts.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package javascript
-
-import (
- "errors"
-
- "github.com/dop251/goja"
-)
-
-func getMapFromValue(val goja.Value) (map[string]any, error) {
- outVal := val.Export()
- v, ok := outVal.(map[string]any)
- if !ok {
- return nil, errors.New("value is not of type map")
- }
- return v, nil
-}
-
-func getSliceFromValue(val goja.Value) ([]any, error) {
- outVal := val.Export()
- v, ok := outVal.([]any)
- if !ok {
- return nil, errors.New("value is not of type slice")
- }
- return v, nil
-}
-
-func getMapSliceFromValue(val goja.Value) ([]map[string]any, error) {
- outVal := val.Export()
- if v, ok := outVal.([]map[string]any); ok {
- return v, nil
- }
- vSlice, ok := outVal.([]any)
- if !ok {
- return nil, errors.New("value is not of type map slice")
- }
- v := make([]map[string]any, len(vSlice))
- for i, e := range vSlice {
- v[i], ok = e.(map[string]any)
- if !ok {
- return nil, errors.New("value is not of type map slice")
- }
- }
- return v, nil
-}
diff --git a/worker/pkg/benthos/javascript/functions.go b/worker/pkg/benthos/javascript/functions.go
deleted file mode 100644
index bf0b147010..0000000000
--- a/worker/pkg/benthos/javascript/functions.go
+++ /dev/null
@@ -1,377 +0,0 @@
-package javascript
-
-import (
- "errors"
- "fmt"
- "io"
- "net/http"
- "strings"
-
- "github.com/dop251/goja"
-
- "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
- "github.com/warpstreamlabs/bento/public/service"
-)
-
-type jsFunction func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error)
-
-type jsFunctionParam struct {
- name string
- typeStr string
- what string
-}
-
-type jsFunctionDefinition struct {
- namespace string
- name string
- description string
- params []jsFunctionParam
- examples []string
- ctor func(r *vmRunner) jsFunction
-}
-
-func (j *jsFunctionDefinition) Param(name, typeStr, what string) *jsFunctionDefinition {
- j.params = append(j.params, jsFunctionParam{
- name: name,
- typeStr: typeStr,
- what: what,
- })
- return j
-}
-
-func (j *jsFunctionDefinition) Example(example string) *jsFunctionDefinition {
- j.examples = append(j.examples, example)
- return j
-}
-
-func (j *jsFunctionDefinition) FnCtor(ctor func(r *vmRunner) jsFunction) *jsFunctionDefinition {
- j.ctor = ctor
- return j
-}
-
-func (j *jsFunctionDefinition) Namespace(namespace string) *jsFunctionDefinition {
- j.namespace = namespace
- return j
-}
-
-func (j *jsFunctionDefinition) String() string {
- var description strings.Builder
-
- _, _ = fmt.Fprintf(&description, "### `benthos.%v`\n\n", j.name)
- _, _ = description.WriteString(j.description + "\n\n")
- if len(j.params) > 0 {
- _, _ = description.WriteString("#### Parameters\n\n")
- for _, p := range j.params {
- _, _ = fmt.Fprintf(&description, "**`%v`** <%v> %v \n", p.name, p.typeStr, p.what)
- }
- _, _ = description.WriteString("\n")
- }
-
- if len(j.examples) > 0 {
- _, _ = description.WriteString("#### Examples\n\n")
- for _, e := range j.examples {
- _, _ = description.WriteString("```javascript\n")
- _, _ = description.WriteString(strings.Trim(e, "\n"))
- _, _ = description.WriteString("\n```\n")
- }
- }
-
- return description.String()
-}
-
-var vmRunnerFunctionCtors = map[string]*jsFunctionDefinition{}
-
-func registerVMRunnerFunction(name, description string) *jsFunctionDefinition {
- fn := &jsFunctionDefinition{
- name: name,
- description: description,
- }
- vmRunnerFunctionCtors[name] = fn
- return fn
-}
-
-func init() {
- // registers neosync transformers
- neosyncTransformers := transformers.GetNeosyncTransformers()
- for _, f := range neosyncTransformers {
- templateData, err := f.GetJsTemplateData()
- if err != nil {
- panic(err)
- }
-
- def := registerVMRunnerFunction(templateData.Name, templateData.Description)
- def.Param("value", "any", "The value to be transformed.")
- def.Param("opts", "object", "Transformer options config")
- def.Example(templateData.Example)
- def.Namespace(neosyncFnCtxName)
- def.FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var (
- value any
- opts map[string]any
- )
- if err := parseArgs(call, &value, &opts); err != nil {
- return nil, err
- }
- goOpts, err := f.ParseOptions(opts)
- if err != nil {
- return nil, err
- }
- return f.Transform(value, goOpts)
- }
- })
- }
-
- // registers neosync generators
- neosyncGenerators := transformers.GetNeosyncGenerators()
- for _, f := range neosyncGenerators {
- templateData, err := f.GetJsTemplateData()
- if err != nil {
- panic(err)
- }
-
- def := registerVMRunnerFunction(templateData.Name, templateData.Description)
- def.Param("opts", "object", "Transformer options config")
- def.Namespace(neosyncFnCtxName)
- def.FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var (
- opts map[string]any
- )
- if err := parseArgs(call, &opts); err != nil {
- return nil, err
- }
- goOpts, err := f.ParseOptions(opts)
- if err != nil {
- return nil, err
- }
- return f.Generate(goOpts)
- }
- })
- }
-}
-
-var _ = registerVMRunnerFunction(
- "v0_fetch",
- `Executes an HTTP request synchronously and returns the result as an object of the form `+"`"+`{"status":200,"body":"foo"}`+"`"+`.`,
-).
- Namespace(benthosFnCtxName).
- Param("url", "string", "The URL to fetch").
- Param("headers", "object(string,string)", "An object of string/string key/value pairs to add the request as headers.").
- Param("method", "string", "The method of the request.").
- Param("body", "(optional) string", "A body to send.").
- Example(`
-let result = benthos.v0_fetch("http://example.com", {}, "GET", "")
-benthos.v0_msg_set_structured(result);
-`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var (
- url string
- httpHeaders map[string]any
- method = "GET"
- payload = ""
- )
- if err := parseArgs(call, &url, &httpHeaders, &method, &payload); err != nil {
- return nil, err
- }
-
- var payloadReader io.Reader
- if payload != "" {
- payloadReader = strings.NewReader(payload)
- }
-
- req, err := http.NewRequest(method, url, payloadReader)
- if err != nil {
- return nil, err
- }
-
- // Parse HTTP headers
- for k, v := range httpHeaders {
- vStr, _ := v.(string)
- req.Header.Add(k, vStr)
- }
-
- // Do request
- resp, err := http.DefaultClient.Do(req)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- respBody, err := io.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- return map[string]any{
- "status": resp.StatusCode,
- "body": string(respBody),
- }, nil
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_set_string", `Set the contents of the processed message to a given string.`).
- Namespace(benthosFnCtxName).
- Param("value", "string", "The value to set it to.").
- Example(`benthos.v0_msg_set_string("hello world");`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var value string
- if err := parseArgs(call, &value); err != nil {
- return nil, err
- }
-
- r.targetMessage.SetBytes([]byte(value))
- return nil, nil
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_as_string", `Obtain the raw contents of the processed message as a string.`).
- Namespace(benthosFnCtxName).
- Example(`let contents = benthos.v0_msg_as_string();`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- b, err := r.targetMessage.AsBytes()
- if err != nil {
- return nil, err
- }
- return string(b), nil
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_set_structured", `Set the root of the processed message to a given value of any type.`).
- Namespace(benthosFnCtxName).
- Param("value", "anything", "The value to set it to.").
- Example(`
-benthos.v0_msg_set_structured({
- "foo": "a thing",
- "bar": "something else",
- "baz": 1234
-});
-`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var value any
- if err := parseArgs(call, &value); err != nil {
- return nil, err
- }
-
- r.targetMessage.SetStructured(value)
- return nil, nil
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_as_structured", `Obtain the root of the processed message as a structured value. If the message is not valid JSON or has not already been expanded into a structured form this function will throw an error.`).
- Namespace(benthosFnCtxName).
- Example(`let foo = benthos.v0_msg_as_structured().foo;`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- return r.targetMessage.AsStructured()
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_exists_meta", `Check that a metadata key exists.`).
- Namespace(benthosFnCtxName).
- Param("name", "string", "The metadata key to search for.").
- Example(`if (benthos.v0_msg_exists_meta("kafka_key")) {}`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var name string
- if err := parseArgs(call, &name); err != nil {
- return nil, err
- }
-
- _, ok := r.targetMessage.MetaGet(name)
- if !ok {
- return false, nil
- }
- return true, nil
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_get_meta", `Get the value of a metadata key from the processed message.`).
- Namespace(benthosFnCtxName).
- Param("name", "string", "The metadata key to search for.").
- Example(`let key = benthos.v0_msg_get_meta("kafka_key");`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var name string
- if err := parseArgs(call, &name); err != nil {
- return nil, err
- }
-
- result, ok := r.targetMessage.MetaGet(name)
- if !ok {
- return nil, errors.New("key not found")
- }
- return result, nil
- }
- })
-
-var _ = registerVMRunnerFunction("v0_msg_set_meta", `Set a metadata key on the processed message to a value.`).
- Namespace(benthosFnCtxName).
- Param("name", "string", "The metadata key to set.").
- Param("value", "anything", "The value to set it to.").
- Example(`benthos.v0_msg_set_meta("thing", "hello world");`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var (
- name string
- value any
- )
- if err := parseArgs(call, &name, &value); err != nil {
- return "", err
- }
- r.targetMessage.MetaSetMut(name, value)
- return nil, nil
- }
- })
-
-var _ = registerVMRunnerFunction("patchStructuredMessage", `Update multiple fields in the structured data of the processed message.`).
- Namespace(neosyncFnCtxName).
- Param("updates", "object", "A map of field names to their new values.").
- Example(`neosync.patchStructuredMessage({"user_id": 12345, "timestamp": "2024-09-23T12:34:56Z"});`).
- FnCtor(func(r *vmRunner) jsFunction {
- return func(call goja.FunctionCall, rt *goja.Runtime, l *service.Logger) (any, error) {
- var updates map[string]any
- if err := parseArgs(call, &updates); err != nil {
- return nil, err
- }
-
- // original structured data
- originalData, err := r.targetMessage.AsStructuredMut()
- if err != nil {
- return nil, fmt.Errorf("failed to get structured data: %w", err)
- }
-
- originalMap, ok := originalData.(map[string]any)
- if !ok {
- return nil, fmt.Errorf("structured data is not a map")
- }
-
- for key, value := range updates {
- setNestedProperty(originalMap, key, value)
- }
-
- r.targetMessage.SetStructured(originalMap)
-
- return nil, nil
- }
- })
-
-func setNestedProperty(obj map[string]any, path string, value any) {
- parts := strings.Split(path, ".")
- current := obj
-
- for i, part := range parts {
- if i == len(parts)-1 {
- current[part] = value
- } else {
- if _, ok := current[part]; !ok {
- current[part] = make(map[string]any)
- }
- current = current[part].(map[string]any)
- }
- }
-}
diff --git a/worker/pkg/benthos/javascript/ifs/http.go b/worker/pkg/benthos/javascript/ifs/http.go
deleted file mode 100644
index eded35ae91..0000000000
--- a/worker/pkg/benthos/javascript/ifs/http.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package ifs
-
-import (
- "errors"
- "io"
- "io/fs"
- "net/http"
-)
-
-var _ http.FileSystem = ToHTTP(OS())
-
-type asHTTP struct {
- f fs.FS
-}
-
-type asHTTPFile struct {
- file fs.File
-}
-
-// ToHTTP converts an fs.FS into an http.FileSystem in a way that doesn't
-// modify the root path.
-func ToHTTP(f fs.FS) *asHTTP {
- return &asHTTP{f: f}
-}
-
-func (h *asHTTP) Open(name string) (http.File, error) {
- f, err := h.f.Open(name)
- if err != nil {
- return nil, err
- }
- return asHTTPFile{file: f}, nil
-}
-
-func (f asHTTPFile) ReadDir(count int) ([]fs.DirEntry, error) {
- d, ok := f.file.(fs.ReadDirFile)
- if !ok {
- return nil, errMissingReadDir
- }
- return d.ReadDir(count)
-}
-
-func (f asHTTPFile) Close() error { return f.file.Close() }
-func (f asHTTPFile) Read(b []byte) (int, error) { return f.file.Read(b) }
-func (f asHTTPFile) Stat() (fs.FileInfo, error) { return f.file.Stat() }
-
-var (
- errMissingSeek = errors.New("io.File missing Seek method")
- errMissingReadDir = errors.New("io.File directory missing ReadDir method")
-)
-
-func (f asHTTPFile) Seek(offset int64, whence int) (int64, error) {
- s, ok := f.file.(io.Seeker)
- if !ok {
- return 0, errMissingSeek
- }
- return s.Seek(offset, whence)
-}
-
-func (f asHTTPFile) Readdir(count int) ([]fs.FileInfo, error) {
- d, ok := f.file.(fs.ReadDirFile)
- if !ok {
- return nil, errMissingReadDir
- }
- var list []fs.FileInfo
- for {
- dirs, err := d.ReadDir(count - len(list))
- for _, dir := range dirs {
- info, err := dir.Info()
- if err != nil {
- // Pretend it doesn't exist, like (*os.File).Readdir does.
- continue
- }
- list = append(list, info)
- }
- if err != nil {
- return list, err
- }
- if count < 0 || len(list) >= count {
- break
- }
- }
- return list, nil
-}
diff --git a/worker/pkg/benthos/javascript/ifs/os.go b/worker/pkg/benthos/javascript/ifs/os.go
deleted file mode 100644
index 6339a10a6f..0000000000
--- a/worker/pkg/benthos/javascript/ifs/os.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package ifs
-
-import (
- "errors"
- "io"
- "io/fs"
- "os"
-)
-
-var _ fs.FS = OS()
-
-// FS is a superset of fs.FS that includes goodies that benthos components
-// specifically need.
-type FS interface {
- Open(name string) (fs.File, error)
- OpenFile(name string, flag int, perm fs.FileMode) (fs.File, error)
- Stat(name string) (fs.FileInfo, error)
- Remove(name string) error
- MkdirAll(path string, perm fs.FileMode) error
-}
-
-// ReadFile opens a file with the RDONLY flag and returns all bytes from it.
-func ReadFile(f fs.FS, name string) ([]byte, error) {
- var i fs.File
- var err error
- if ef, ok := f.(FS); ok {
- i, err = ef.OpenFile(name, os.O_RDONLY, 0)
- } else {
- i, err = f.Open(name)
- }
- if err != nil {
- return nil, err
- }
- return io.ReadAll(i)
-}
-
-// WriteFile opens a file with O_WRONLY|O_CREATE|O_TRUNC flags and writes the
-// data to it.
-func WriteFile(f fs.FS, name string, data []byte, perm fs.FileMode) error {
- h, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
- if err != nil {
- return err
- }
- _, err = h.Write(data)
- if err1 := h.Close(); err1 != nil && err == nil {
- err = err1
- }
- return err
-}
-
-// FileWrite attempts to write to an fs.File provided it supports io.Writer.
-func FileWrite(file fs.File, data []byte) (int, error) {
- writer, isw := file.(io.Writer)
- if !isw {
- return 0, errors.New("failed to open a writable file")
- }
- return writer.Write(data)
-}
-
-// OS implements fs.FS as if calls were being made directly via the os package,
-// with which relative paths are resolved from the directory the process is
-// executed from.
-func OS() FS {
- return osPTI
-}
-
-// IsOS returns true if the provided FS implementation is a wrapper around OS
-// access obtained via OS().
-func IsOS(f FS) bool {
- return f == osPTI
-}
-
-var osPTI = &osPT{}
-
-type osPT struct{}
-
-func (o *osPT) Open(name string) (fs.File, error) {
- return os.Open(name)
-}
-
-func (o *osPT) OpenFile(name string, flag int, perm fs.FileMode) (fs.File, error) {
- return os.OpenFile(name, flag, perm)
-}
-
-func (o *osPT) Stat(name string) (fs.FileInfo, error) {
- return os.Stat(name)
-}
-
-func (o *osPT) Remove(name string) error {
- return os.Remove(name)
-}
-
-func (o *osPT) MkdirAll(path string, perm fs.FileMode) error {
- return os.MkdirAll(path, perm)
-}
diff --git a/worker/pkg/benthos/javascript/ifs/os_test.go b/worker/pkg/benthos/javascript/ifs/os_test.go
deleted file mode 100644
index cdad9a4d80..0000000000
--- a/worker/pkg/benthos/javascript/ifs/os_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package ifs
-
-import (
- "errors"
- "io/fs"
- "testing"
- "testing/fstest"
-
- "github.com/stretchr/testify/require"
-)
-
-type testFS struct {
- fstest.MapFS
-}
-
-func (t testFS) MkdirAll(path string, perm fs.FileMode) error {
- return errors.New("not implemented")
-}
-
-func (t testFS) OpenFile(name string, flag int, perm fs.FileMode) (fs.File, error) {
- return nil, errors.New("not implemented")
-}
-
-func (t testFS) Remove(name string) error {
- return errors.New("not implemented")
-}
-
-func TestOSAccess(t *testing.T) {
- var fss FS = testFS{}
-
- require.False(t, IsOS(fss))
-
- fss = OS()
-
- require.True(t, IsOS(fss))
-}
diff --git a/worker/pkg/benthos/javascript/logger.go b/worker/pkg/benthos/javascript/logger.go
deleted file mode 100644
index ca138ff825..0000000000
--- a/worker/pkg/benthos/javascript/logger.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package javascript
-
-import "github.com/warpstreamlabs/bento/public/service"
-
-// Logger wraps the service.Logger so that we can define the below methods.
-type Logger struct {
- l *service.Logger
-}
-
-// Log will be used for "console.log()" in JS
-func (l *Logger) Log(message string) {
- l.l.Info(message)
-}
-
-// Warn will be used for "console.warn()" in JS
-func (l *Logger) Warn(message string) {
- l.l.Warn(message)
-}
-
-// Error will be used for "console.error()" in JS
-func (l *Logger) Error(message string) {
- l.l.Error(message)
-}
diff --git a/worker/pkg/benthos/javascript/processor.go b/worker/pkg/benthos/javascript/processor.go
index 64083ec632..18498d844b 100644
--- a/worker/pkg/benthos/javascript/processor.go
+++ b/worker/pkg/benthos/javascript/processor.go
@@ -1,243 +1,121 @@
-package javascript
+package javascript_processor
import (
"context"
- "errors"
"fmt"
- "io"
- "io/fs"
- "path/filepath"
- "runtime"
- "sort"
- "strings"
+ "log/slog"
"sync"
- "syscall"
"github.com/dop251/goja"
- "github.com/dop251/goja_nodejs/console"
- "github.com/dop251/goja_nodejs/require"
+ "github.com/nucleuscloud/neosync/internal/benthos_slogger"
+ "github.com/nucleuscloud/neosync/internal/javascript"
+ javascript_vm "github.com/nucleuscloud/neosync/internal/javascript/vm"
- "github.com/nucleuscloud/neosync/worker/pkg/benthos/javascript/ifs"
"github.com/warpstreamlabs/bento/public/service"
)
const (
- codeField = "code"
- fileField = "file"
- includeField = "global_folders"
+ codeField = "code"
)
func javascriptProcessorConfig() *service.ConfigSpec {
- functionsSlice := make([]string, 0, len(vmRunnerFunctionCtors))
- for k := range vmRunnerFunctionCtors {
- functionsSlice = append(functionsSlice, k)
- }
- sort.Strings(functionsSlice)
-
- var description strings.Builder
- for _, name := range functionsSlice {
- _, _ = description.WriteString("\n")
- _, _ = description.WriteString(vmRunnerFunctionCtors[name].String())
- }
-
return service.NewConfigSpec().
- Categories("Mapping").
- Version("4.14.0").
- Summary("Executes a provided JavaScript code block or file for each message.").
- Description(`
-The [execution engine](https://github.com/dop251/goja) behind this processor provides full ECMAScript 5.1 support (including regex and strict mode). Most of the ECMAScript 6 spec is implemented but this is a work in progress.
-
-Imports via `+"`require`"+` should work similarly to NodeJS, and access to the console is supported which will print via the Benthos logger. More caveats can be [found here](https://github.com/dop251/goja#known-incompatibilities-and-caveats).
-
-This processor is implemented using the [github.com/dop251/goja](https://github.com/dop251/goja) library.`).
- Footnotes(`
-## Runtime
-
-In order to optimize code execution JS runtimes are created on demand (in order to support parallel execution) and are reused across invocations. Therefore, it is important to understand that global state created by your programs will outlive individual invocations. In order for your programs to avoid failing after the first invocation ensure that you do not define variables at the global scope.
-
-Although technically possible, it is recommended that you do not rely on the global state for maintaining state across invocations as the pooling nature of the runtimes will prevent deterministic behavior. We aim to support deterministic strategies for mutating global state in the future.
-
-## Functions
-`+description.String()+`
-`).
- Field(service.NewInterpolatedStringField(codeField).
- Description("An inline JavaScript program to run. One of `"+codeField+"` or `"+fileField+"` must be defined.").
- Optional()).
- Field(service.NewInterpolatedStringField(fileField).
- Description("A file containing a JavaScript program to run. One of `"+codeField+"` or `"+fileField+"` must be defined.").
- Optional()).
- Field(service.NewStringListField(includeField).
- Description("List of folders that will be used to load modules from if the requested JS module is not found elsewhere.").
- Default([]string{})).
- LintRule(fmt.Sprintf(`
-let codeLen = (this.%v | "").length()
-let fileLen = (this.%v | "").length()
-root = if $codeLen == 0 && $fileLen == 0 {
- "either the code or file field must be specified"
-} else if $codeLen > 0 && $fileLen > 0 {
- "cannot specify both the code and file fields"
-}`, codeField, fileField)).
- Example(
- `Simple mutation`,
- `In this example we define a simple function that performs a basic mutation against messages, treating their contents as raw strings.`,
- `
-pipeline:
- processors:
- - javascript:
- code: 'benthos.v0_msg_set_string(benthos.v0_msg_as_string() + "hello world");'
-`,
- ).
- Example(
- `Structured mutation`,
- `In this example we define a function that performs basic mutations against a structured message. Note that we encapsulate the logic within an anonymous function that is called for each invocation, this is required in order to avoid duplicate variable declarations in the global state.`,
- `
-pipeline:
- processors:
- - javascript:
- code: |
- (() => {
- let thing = benthos.v0_msg_as_structured();
- thing.num_keys = Object.keys(thing).length;
- delete thing["b"];
- benthos.v0_msg_set_structured(thing);
- })();
-`,
- )
+ Field(service.NewInterpolatedStringField(codeField))
}
-// func RegisterNeosyncJavascriptProcessor() error {
-// return service.RegisterBatchProcessor(
-// "javascript", javascriptProcessorConfig(),
-// func(conf *service.ParsedConfig, mgr *service.Resources) (service.BatchProcessor, error) {
-// return newJavascriptProcessorFromConfig(conf, mgr)
-// })
-
-// }
-
-func init() {
- err := service.RegisterBatchProcessor(
+func RegisterNeosyncJavascriptProcessor(env *service.Environment) error {
+ return env.RegisterBatchProcessor(
"neosync_javascript", javascriptProcessorConfig(),
func(conf *service.ParsedConfig, mgr *service.Resources) (service.BatchProcessor, error) {
return newJavascriptProcessorFromConfig(conf, mgr)
})
- if err != nil {
- panic(err)
- }
}
-//------------------------------------------------------------------------------
-
type javascriptProcessor struct {
- program *goja.Program
- requireRegistry *require.Registry
- logger *service.Logger
- vmPool sync.Pool
-}
-
-func sourceLoader(serviceFS *service.FS) require.SourceLoader {
- // Copy of `require.DefaultSourceLoader`: https://github.com/dop251/goja_nodejs/blob/e84d9a924c5ca9e541575e643b7efbca5705862f/require/module.go#L116-L141
- // with some slight adjustments because we need to use the Benthos manager filesystem for opening and reading files.
- return func(filename string) ([]byte, error) {
- fp := filepath.FromSlash(filename)
- f, err := serviceFS.Open(fp)
- if err != nil {
- if errors.Is(err, fs.ErrNotExist) {
- err = require.ModuleFileDoesNotExistError
- } else if runtime.GOOS == "windows" {
- if errors.Is(err, syscall.Errno(0x7b)) { // ERROR_INVALID_NAME, The filename, directory name, or volume label syntax is incorrect.
- err = require.ModuleFileDoesNotExistError
- }
- }
- return nil, err
- }
-
- defer f.Close()
- // On some systems (e.g. plan9 and FreeBSD) it is possible to use the standard read() call on directories
- // which means we cannot rely on read() returning an error, we have to do stat() instead.
- if fi, err := f.Stat(); err == nil {
- if fi.IsDir() {
- return nil, require.ModuleFileDoesNotExistError
- }
- } else {
- return nil, err
- }
-
- return io.ReadAll(f)
- }
+ program *goja.Program
+ slogger *slog.Logger
+ vmPool sync.Pool
}
func newJavascriptProcessorFromConfig(conf *service.ParsedConfig, mgr *service.Resources) (*javascriptProcessor, error) {
- code, _ := conf.FieldString(codeField)
- file, _ := conf.FieldString(fileField)
- if file == "" && code == "" {
- return nil, fmt.Errorf("either a `%v` or `%v` must be specified", codeField, fileField)
+ code, err := conf.FieldString(codeField)
+ if err != nil {
+ return nil, err
}
filename := "main.js"
- if file != "" {
- // Open file and read code
- codeBytes, err := ifs.ReadFile(mgr.FS(), file)
- if err != nil {
- return nil, fmt.Errorf("failed to open target file: %w", err)
- }
- filename = file
- code = string(codeBytes)
- }
-
program, err := goja.Compile(filename, code, false)
if err != nil {
return nil, fmt.Errorf("failed to compile javascript code: %v", err)
}
logger := mgr.Logger()
- registryGlobalFolders, err := conf.FieldStringList(includeField)
- if err != nil {
- return nil, err
- }
- requireRegistry := require.NewRegistry(
- require.WithGlobalFolders(registryGlobalFolders...),
- require.WithLoader(sourceLoader(mgr.FS())),
- )
- requireRegistry.RegisterNativeModule("console", console.RequireWithPrinter(&Logger{logger}))
+ slogger := benthos_slogger.NewSlogger(logger)
return &javascriptProcessor{
- program: program,
- requireRegistry: requireRegistry,
- logger: logger,
- vmPool: sync.Pool{},
+ program: program,
+ slogger: slogger,
+ vmPool: sync.Pool{
+ New: func() any {
+ val, err := newPoolItem(slogger)
+ if err != nil {
+ return err
+ }
+ return val
+ },
+ },
}, nil
}
+type vmPoolItem struct {
+ runner *javascript_vm.Runner
+ valueApi *benthosValueApi
+}
+
func (j *javascriptProcessor) ProcessBatch(ctx context.Context, batch service.MessageBatch) ([]service.MessageBatch, error) {
- var vr *vmRunner
- var err error
- if vmRunnerPtr := j.vmPool.Get(); vmRunnerPtr != nil {
- vr = vmRunnerPtr.(*vmRunner)
- } else {
- if vr, err = j.newVM(); err != nil {
+ var runner *javascript_vm.Runner
+ var valueApi *benthosValueApi
+
+ switch poolItem := j.vmPool.Get().(type) {
+ case *vmPoolItem:
+ runner = poolItem.runner
+ valueApi = poolItem.valueApi
+ defer func() {
+ poolItem.valueApi.SetMessage(nil) // reset the message to nil
+ j.vmPool.Put(poolItem)
+ }()
+ case error:
+ return nil, poolItem
+ }
+
+ var newBatch service.MessageBatch
+
+ for i := range batch {
+ valueApi.SetMessage(batch[i])
+ _, err := runner.Run(ctx, j.program)
+ if err != nil {
return nil, err
}
+ if newMsg := valueApi.Message(); newMsg != nil {
+ newBatch = append(newBatch, newMsg)
+ }
}
- defer func() {
- // TODO: Decide whether to reset the program
- j.vmPool.Put(vr)
- }()
- b, err := vr.Run(ctx, batch)
- if err != nil {
- return nil, err
- }
- return []service.MessageBatch{b}, nil
+ return []service.MessageBatch{newBatch}, nil
}
func (j *javascriptProcessor) Close(ctx context.Context) error {
- for {
- mr := j.vmPool.Get()
- if mr == nil {
- return nil
- }
- if err := mr.(*vmRunner).Close(ctx); err != nil {
- return err
- }
+ return nil
+}
+
+func newPoolItem(logger *slog.Logger) (*vmPoolItem, error) {
+ valueApi := newBatchBenthosValueApi()
+ runner, err := javascript.NewDefaultValueRunner(valueApi, logger)
+ if err != nil {
+ return nil, err
}
+ return &vmPoolItem{
+ valueApi: valueApi,
+ runner: runner,
+ }, nil
}
diff --git a/worker/pkg/benthos/javascript/processor_test.go b/worker/pkg/benthos/javascript/processor_test.go
index 4b4a1e3306..6d5c7c73d2 100644
--- a/worker/pkg/benthos/javascript/processor_test.go
+++ b/worker/pkg/benthos/javascript/processor_test.go
@@ -1,4 +1,4 @@
-package javascript
+package javascript_processor
import (
"bytes"
@@ -7,8 +7,6 @@ import (
"io"
"net/http"
"net/http/httptest"
- "os"
- "path"
"testing"
"time"
@@ -254,87 +252,6 @@ code: |
require.NoError(t, proc.Close(bCtx))
}
-func TestProcessorBasicFromFile(t *testing.T) {
- tmpDir := t.TempDir()
- require.NoError(t, os.WriteFile(path.Join(tmpDir, "foo.js"), []byte(`
-(() => {
- let foo = "hello world"
- benthos.v0_msg_set_string(benthos.v0_msg_as_string() + foo);
-})();
-`), 0o644))
-
- conf, err := javascriptProcessorConfig().ParseYAML(fmt.Sprintf(`
-file: %v
-`, path.Join(tmpDir, "foo.js")), nil)
- require.NoError(t, err)
-
- proc, err := newJavascriptProcessorFromConfig(conf, service.MockResources())
- require.NoError(t, err)
-
- bCtx, done := context.WithTimeout(context.Background(), time.Second*30)
- defer done()
-
- resBatches, err := proc.ProcessBatch(bCtx, service.MessageBatch{
- service.NewMessage([]byte("first ")),
- service.NewMessage([]byte("second ")),
- })
- require.NoError(t, err)
- require.Len(t, resBatches, 1)
- require.Len(t, resBatches[0], 2)
-
- resBytes, err := resBatches[0][0].AsBytes()
- require.NoError(t, err)
- assert.Equal(t, "first hello world", string(resBytes))
-
- resBytes, err = resBatches[0][1].AsBytes()
- require.NoError(t, err)
- assert.Equal(t, "second hello world", string(resBytes))
-
- require.NoError(t, proc.Close(bCtx))
-}
-
-func TestProcessorBasicFromModule(t *testing.T) {
- tmpDir := t.TempDir()
- // The file must have the .js extension and be imported without it using `require('blobber')`
- require.NoError(t, os.WriteFile(path.Join(tmpDir, "blobber.js"), []byte(`
-function blobber() {
- return 'blobber module';
-}
-
-module.exports = blobber;
-`), 0o644))
-
- conf, err := javascriptProcessorConfig().ParseYAML(fmt.Sprintf(`
-code: |
- (() => {
- const blobber = require('blobber');
-
- benthos.v0_msg_set_string(benthos.v0_msg_as_string() + blobber());
- })();
-global_folders: [ "%s" ]
-`, tmpDir), nil)
- require.NoError(t, err)
-
- proc, err := newJavascriptProcessorFromConfig(conf, service.MockResources())
- require.NoError(t, err)
-
- bCtx, done := context.WithTimeout(context.Background(), time.Second*30)
- defer done()
-
- resBatches, err := proc.ProcessBatch(bCtx, service.MessageBatch{
- service.NewMessage([]byte("hello ")),
- })
- require.NoError(t, err)
- require.Len(t, resBatches, 1)
- require.Len(t, resBatches[0], 1)
-
- resBytes, err := resBatches[0][0].AsBytes()
- require.NoError(t, err)
- assert.Equal(t, "hello blobber module", string(resBytes))
-
- require.NoError(t, proc.Close(bCtx))
-}
-
func TestProcessorHTTPFetch(t *testing.T) {
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
bodyBytes, err := io.ReadAll(r.Body)
diff --git a/worker/pkg/benthos/javascript/vm.go b/worker/pkg/benthos/javascript/vm.go
deleted file mode 100644
index 9457012b4b..0000000000
--- a/worker/pkg/benthos/javascript/vm.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package javascript
-
-import (
- "context"
- "fmt"
-
- "github.com/dop251/goja"
- "github.com/dop251/goja_nodejs/console"
-
- "github.com/warpstreamlabs/bento/public/service"
-)
-
-type vmRunner struct {
- vm *goja.Runtime
- p *goja.Program
-
- logger *service.Logger
-
- runBatch service.MessageBatch
- targetMessage *service.Message
- targetIndex int
-}
-
-func (j *javascriptProcessor) newVM() (*vmRunner, error) {
- vm := goja.New()
-
- j.requireRegistry.Enable(vm)
- console.Enable(vm)
-
- vr := &vmRunner{
- vm: vm,
- logger: j.logger,
- p: j.program,
- }
-
- for name, fc := range vmRunnerFunctionCtors {
- if err := setFunction(vr, fc.namespace, name, fc.ctor(vr)); err != nil {
- return nil, err
- }
- }
- return vr, nil
-}
-
-// The namespace within all our function definitions
-const benthosFnCtxName = "benthos"
-const neosyncFnCtxName = "neosync"
-
-func setFunction(vr *vmRunner, namespace, name string, function jsFunction) error {
- var targetObj *goja.Object
- if targetObjValue := vr.vm.GlobalObject().Get(namespace); targetObjValue != nil {
- targetObj = targetObjValue.ToObject(vr.vm)
- }
- if targetObj == nil {
- if err := vr.vm.GlobalObject().Set(namespace, map[string]any{}); err != nil {
- return fmt.Errorf("failed to set global %s object: %w", namespace, err)
- }
- targetObj = vr.vm.GlobalObject().Get(namespace).ToObject(vr.vm)
- }
-
- if err := targetObj.Set(name, func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
- l := vr.logger.With("function", name)
- result, err := function(call, rt, l)
- if err != nil {
- panic(rt.ToValue(err.Error()))
- }
- return rt.ToValue(result)
- }); err != nil {
- return fmt.Errorf("failed to set global %s function %v: %w", namespace, name, err)
- }
-
- return nil
-}
-
-func parseArgs(call goja.FunctionCall, ptrs ...any) error {
- if len(ptrs) < len(call.Arguments) {
- return fmt.Errorf("have %d arguments, but only %d pointers to parse into", len(call.Arguments), len(ptrs))
- }
-
- for i := 0; i < len(call.Arguments); i++ {
- arg, ptr := call.Argument(i), ptrs[i]
-
- if goja.IsUndefined(arg) {
- return fmt.Errorf("argument at position %d is undefined", i)
- }
-
- var err error
- switch p := ptr.(type) {
- case *string:
- *p = arg.String()
- case *int:
- *p = int(arg.ToInteger())
- case *int64:
- *p = arg.ToInteger()
- case *float64:
- *p = arg.ToFloat()
- case *map[string]any:
- *p, err = getMapFromValue(arg)
- case *bool:
- *p = arg.ToBoolean()
- case *[]any:
- *p, err = getSliceFromValue(arg)
- case *[]map[string]any:
- *p, err = getMapSliceFromValue(arg)
- case *goja.Value:
- *p = arg
- case *any:
- *p = arg.Export()
- default:
- return fmt.Errorf("encountered unhandled type %T while trying to parse %v into %v", arg.ExportType().String(), arg, p)
- }
- if err != nil {
- return fmt.Errorf("could not parse %v (%s) into %v (%T): %v", arg, arg.ExportType().String(), ptr, ptr, err)
- }
- }
-
- return nil
-}
-
-func (r *vmRunner) reset() {
- r.runBatch = nil
- r.targetMessage = nil
- r.targetIndex = 0
-}
-
-func (r *vmRunner) Run(ctx context.Context, batch service.MessageBatch) (service.MessageBatch, error) {
- defer r.reset()
-
- var newBatch service.MessageBatch
- for i := range batch {
- r.reset()
- r.runBatch = batch
- r.targetIndex = i
- r.targetMessage = batch[i]
-
- _, err := r.vm.RunProgram(r.p)
- if err != nil {
- // TODO: Make this more granular, error could be message specific
- return nil, err
- }
- if newMsg := r.targetMessage; newMsg != nil {
- newBatch = append(newBatch, newMsg)
- }
- }
- return newBatch, nil
-}
-
-func (r *vmRunner) Close(ctx context.Context) error {
- return nil
-}
diff --git a/worker/pkg/benthos/transformer_executor/anon_value_api.go b/worker/pkg/benthos/transformer_executor/anon_value_api.go
new file mode 100644
index 0000000000..2274aa7962
--- /dev/null
+++ b/worker/pkg/benthos/transformer_executor/anon_value_api.go
@@ -0,0 +1,74 @@
+package transformer_executor
+
+import (
+ "encoding/json"
+ "fmt"
+
+ javascript_functions "github.com/nucleuscloud/neosync/internal/javascript/functions"
+ "github.com/warpstreamlabs/bento/public/service"
+)
+
+type anonValueApi struct {
+ message *service.Message
+}
+
+var _ javascript_functions.ValueApi = (*anonValueApi)(nil)
+
+func newAnonValueApi() *anonValueApi {
+ return &anonValueApi{}
+}
+
+func (b *anonValueApi) SetMessage(message *service.Message) {
+ b.message = message
+}
+
+func (b *anonValueApi) Message() *service.Message {
+ return b.message
+}
+
+func (b *anonValueApi) SetBytes(bytes []byte) {
+ b.message.SetBytes(bytes)
+}
+
+func (b *anonValueApi) AsBytes() ([]byte, error) {
+ return b.message.AsBytes()
+}
+
+func (b *anonValueApi) SetStructured(value any) {
+ b.message.SetStructured(value)
+}
+
+func (b *anonValueApi) AsStructured() (any, error) {
+ return b.message.AsStructured()
+}
+
+func (b *anonValueApi) MetaGet(key string) (any, bool) {
+ return b.message.MetaGet(key)
+}
+
+func (b *anonValueApi) MetaSetMut(key string, value any) {
+ b.message.MetaSetMut(key, value)
+}
+
+func (b *anonValueApi) GetPropertyPathValue(propertyPath string) (any, error) {
+ if b.message == nil {
+ return nil, fmt.Errorf("message is nil")
+ }
+ structuredValue, err := b.message.AsStructured()
+ if err != nil {
+ return nil, fmt.Errorf("failed to get structured message: %w", err)
+ }
+ structuredValueMap, ok := structuredValue.(map[string]any)
+ if !ok {
+ return nil, fmt.Errorf("structured value is not a map[string]any")
+ }
+ return structuredValueMap[propertyPath], nil
+}
+
+func NewMessage(input map[string]any) (*service.Message, error) {
+ bits, err := json.Marshal(input)
+ if err != nil {
+ return nil, fmt.Errorf("failed to marshal input map: %w", err)
+ }
+ return service.NewMessage(bits), nil
+}
diff --git a/worker/pkg/benthos/transformer_executor/anon_value_api_test.go b/worker/pkg/benthos/transformer_executor/anon_value_api_test.go
new file mode 100644
index 0000000000..611c2a5aac
--- /dev/null
+++ b/worker/pkg/benthos/transformer_executor/anon_value_api_test.go
@@ -0,0 +1,17 @@
+package transformer_executor
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func Test_AnonValueApi_getPropertyPathValue(t *testing.T) {
+ message, err := NewMessage(map[string]any{"a": "b"})
+ require.NoError(t, err)
+ api := newAnonValueApi()
+ api.SetMessage(message)
+ value, err := api.GetPropertyPathValue("a")
+ require.NoError(t, err)
+ require.Equal(t, "b", value)
+}
diff --git a/worker/pkg/benthos/transformers/transformer_initializer.go b/worker/pkg/benthos/transformer_executor/executor.go
similarity index 67%
rename from worker/pkg/benthos/transformers/transformer_initializer.go
rename to worker/pkg/benthos/transformer_executor/executor.go
index f8c2ddb93d..6efbbd56df 100644
--- a/worker/pkg/benthos/transformers/transformer_initializer.go
+++ b/worker/pkg/benthos/transformer_executor/executor.go
@@ -1,4 +1,4 @@
-package transformers
+package transformer_executor
import (
"context"
@@ -6,9 +6,13 @@ import (
"fmt"
"log/slog"
+ "github.com/dop251/goja"
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
presidioapi "github.com/nucleuscloud/neosync/internal/ee/presidio"
ee_transformer_fns "github.com/nucleuscloud/neosync/internal/ee/transformers/functions"
+ "github.com/nucleuscloud/neosync/internal/javascript"
+ javascript_userland "github.com/nucleuscloud/neosync/internal/javascript/userland"
+ "github.com/nucleuscloud/neosync/worker/pkg/benthos/transformers"
)
type TransformerExecutor struct {
@@ -85,6 +89,80 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
return nil, err
}
return InitializeTransformerByConfigType(resolvedConfig, opts...)
+ case *mgmtv1alpha1.TransformerConfig_GenerateJavascriptConfig:
+ config := typedCfg.GenerateJavascriptConfig
+ if config == nil {
+ return nil, fmt.Errorf("generate javascript config is nil")
+ }
+
+ valueApi := newAnonValueApi()
+ runner, err := javascript.NewDefaultValueRunner(valueApi, execCfg.logger)
+ if err != nil {
+ return nil, err
+ }
+ jsCode, propertyPath := javascript_userland.GetSingleGenerateFunction(config.GetCode())
+ program, err := goja.Compile("main.js", jsCode, false)
+ if err != nil {
+ return nil, err
+ }
+
+ return &TransformerExecutor{
+ Opts: nil,
+ Mutate: func(value any, opts any) (any, error) {
+ inputMessage, err := NewMessage(map[string]any{})
+ if err != nil {
+ return nil, fmt.Errorf("failed to create input message: %w", err)
+ }
+ valueApi.SetMessage(inputMessage)
+ _, err = runner.Run(context.Background(), program)
+ if err != nil {
+ return nil, fmt.Errorf("failed to run program: %w", err)
+ }
+ updatedValue, err := valueApi.GetPropertyPathValue(propertyPath)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get property path value: %w", err)
+ }
+ return updatedValue, nil
+ },
+ }, nil
+ case *mgmtv1alpha1.TransformerConfig_TransformJavascriptConfig:
+ config := typedCfg.TransformJavascriptConfig
+ if config == nil {
+ return nil, fmt.Errorf("transform javascript config is nil")
+ }
+
+ valueApi := newAnonValueApi()
+ runner, err := javascript.NewDefaultValueRunner(valueApi, execCfg.logger)
+ if err != nil {
+ return nil, err
+ }
+ jsCode, propertyPath := javascript_userland.GetSingleTransformFunction(config.GetCode())
+ program, err := goja.Compile("main.js", jsCode, false)
+ if err != nil {
+ return nil, err
+ }
+
+ return &TransformerExecutor{
+ Opts: nil,
+ Mutate: func(value any, opts any) (any, error) {
+ inputMessage, err := NewMessage(map[string]any{
+ propertyPath: value,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("failed to create input message: %w", err)
+ }
+ valueApi.SetMessage(inputMessage)
+ _, err = runner.Run(context.Background(), program)
+ if err != nil {
+ return nil, fmt.Errorf("failed to run program: %w", err)
+ }
+ updatedValue, err := valueApi.GetPropertyPathValue(propertyPath)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get property path value: %w", err)
+ }
+ return updatedValue, nil
+ },
+ }, nil
case *mgmtv1alpha1.TransformerConfig_PassthroughConfig:
return &TransformerExecutor{
Opts: nil,
@@ -94,11 +172,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
}, nil
case *mgmtv1alpha1.TransformerConfig_GenerateCategoricalConfig:
config := transformerConfig.GetGenerateCategoricalConfig()
- opts, err := NewGenerateCategoricalOptsFromConfig(config)
+ opts, err := transformers.NewGenerateCategoricalOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateCategorical().Generate
+ generate := transformers.NewGenerateCategorical().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -108,11 +186,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateBoolConfig:
config := transformerConfig.GetGenerateBoolConfig()
- opts, err := NewGenerateBoolOptsFromConfig(config)
+ opts, err := transformers.NewGenerateBoolOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateBool().Generate
+ generate := transformers.NewGenerateBool().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -123,11 +201,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformStringConfig:
config := transformerConfig.GetTransformStringConfig()
minLength := int64(3) // TODO: pull this value from the database schema
- opts, err := NewTransformStringOptsFromConfig(config, &minLength, &maxLength)
+ opts, err := transformers.NewTransformStringOptsFromConfig(config, &minLength, &maxLength)
if err != nil {
return nil, err
}
- transform := NewTransformString().Transform
+ transform := transformers.NewTransformString().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -136,11 +214,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
}, nil
case *mgmtv1alpha1.TransformerConfig_TransformInt64Config:
config := transformerConfig.GetTransformInt64Config()
- opts, err := NewTransformInt64OptsFromConfig(config)
+ opts, err := transformers.NewTransformInt64OptsFromConfig(config)
if err != nil {
return nil, err
}
- transform := NewTransformInt64().Transform
+ transform := transformers.NewTransformInt64().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -150,11 +228,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformFullNameConfig:
config := transformerConfig.GetTransformFullNameConfig()
- opts, err := NewTransformFullNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewTransformFullNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- transform := NewTransformFullName().Transform
+ transform := transformers.NewTransformFullName().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -164,11 +242,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateEmailConfig:
config := transformerConfig.GetGenerateEmailConfig()
- opts, err := NewGenerateEmailOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateEmailOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateEmail().Generate
+ generate := transformers.NewGenerateEmail().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -178,11 +256,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformEmailConfig:
config := transformerConfig.GetTransformEmailConfig()
- opts, err := NewTransformEmailOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewTransformEmailOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- transform := NewTransformEmail().Transform
+ transform := transformers.NewTransformEmail().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -192,11 +270,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateCardNumberConfig:
config := transformerConfig.GetGenerateCardNumberConfig()
- opts, err := NewGenerateCardNumberOptsFromConfig(config)
+ opts, err := transformers.NewGenerateCardNumberOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateCardNumber().Generate
+ generate := transformers.NewGenerateCardNumber().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -206,11 +284,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateCityConfig:
config := transformerConfig.GetGenerateCityConfig()
- opts, err := NewGenerateCityOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateCityOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateCity().Generate
+ generate := transformers.NewGenerateCity().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -220,11 +298,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateE164PhoneNumberConfig:
config := transformerConfig.GetGenerateE164PhoneNumberConfig()
- opts, err := NewGenerateInternationalPhoneNumberOptsFromConfig(config)
+ opts, err := transformers.NewGenerateInternationalPhoneNumberOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateInternationalPhoneNumber().Generate
+ generate := transformers.NewGenerateInternationalPhoneNumber().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -233,11 +311,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
}, nil
case *mgmtv1alpha1.TransformerConfig_GenerateFirstNameConfig:
config := transformerConfig.GetGenerateFirstNameConfig()
- opts, err := NewGenerateFirstNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateFirstNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateFirstName().Generate
+ generate := transformers.NewGenerateFirstName().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -247,11 +325,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateFloat64Config:
config := transformerConfig.GetGenerateFloat64Config()
- opts, err := NewGenerateFloat64OptsFromConfig(config, nil)
+ opts, err := transformers.NewGenerateFloat64OptsFromConfig(config, nil)
if err != nil {
return nil, err
}
- generate := NewGenerateFloat64().Generate
+ generate := transformers.NewGenerateFloat64().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -261,11 +339,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateFullAddressConfig:
config := transformerConfig.GetGenerateFullAddressConfig()
- opts, err := NewGenerateFullAddressOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateFullAddressOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateFullAddress().Generate
+ generate := transformers.NewGenerateFullAddress().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -275,11 +353,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateFullNameConfig:
config := transformerConfig.GetGenerateFullNameConfig()
- opts, err := NewGenerateFullNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateFullNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateFullName().Generate
+ generate := transformers.NewGenerateFullName().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -289,11 +367,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateGenderConfig:
config := transformerConfig.GetGenerateGenderConfig()
- opts, err := NewGenerateGenderOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateGenderOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateGender().Generate
+ generate := transformers.NewGenerateGender().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -303,11 +381,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateInt64PhoneNumberConfig:
config := transformerConfig.GetGenerateInt64PhoneNumberConfig()
- opts, err := NewGenerateInt64PhoneNumberOptsFromConfig(config)
+ opts, err := transformers.NewGenerateInt64PhoneNumberOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateInt64PhoneNumber().Generate
+ generate := transformers.NewGenerateInt64PhoneNumber().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -317,11 +395,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateInt64Config:
config := transformerConfig.GetGenerateInt64Config()
- opts, err := NewGenerateInt64OptsFromConfig(config)
+ opts, err := transformers.NewGenerateInt64OptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateInt64().Generate
+ generate := transformers.NewGenerateInt64().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -331,11 +409,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateLastNameConfig:
config := transformerConfig.GetGenerateLastNameConfig()
- opts, err := NewGenerateLastNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateLastNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateLastName().Generate
+ generate := transformers.NewGenerateLastName().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -345,11 +423,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateSha256HashConfig:
config := transformerConfig.GetGenerateSha256HashConfig()
- opts, err := NewGenerateSHA256HashOptsFromConfig(config)
+ opts, err := transformers.NewGenerateSHA256HashOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateSHA256Hash().Generate
+ generate := transformers.NewGenerateSHA256Hash().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -359,11 +437,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateSsnConfig:
config := transformerConfig.GetGenerateSsnConfig()
- opts, err := NewGenerateSSNOptsFromConfig(config)
+ opts, err := transformers.NewGenerateSSNOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateSSN().Generate
+ generate := transformers.NewGenerateSSN().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -373,11 +451,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateStateConfig:
config := transformerConfig.GetGenerateStateConfig()
- opts, err := NewGenerateStateOptsFromConfig(config)
+ opts, err := transformers.NewGenerateStateOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateState().Generate
+ generate := transformers.NewGenerateState().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -387,11 +465,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateStreetAddressConfig:
config := transformerConfig.GetGenerateStreetAddressConfig()
- opts, err := NewGenerateStreetAddressOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateStreetAddressOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateStreetAddress().Generate
+ generate := transformers.NewGenerateStreetAddress().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -401,11 +479,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateStringPhoneNumberConfig:
config := transformerConfig.GetGenerateStringPhoneNumberConfig()
- opts, err := NewGenerateStringPhoneNumberOptsFromConfig(config)
+ opts, err := transformers.NewGenerateStringPhoneNumberOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateStringPhoneNumber().Generate
+ generate := transformers.NewGenerateStringPhoneNumber().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -415,11 +493,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateStringConfig:
config := transformerConfig.GetGenerateStringConfig()
- opts, err := NewGenerateRandomStringOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateRandomStringOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateRandomString().Generate
+ generate := transformers.NewGenerateRandomString().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -429,11 +507,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateUnixtimestampConfig:
config := transformerConfig.GetGenerateUnixtimestampConfig()
- opts, err := NewGenerateUnixTimestampOptsFromConfig(config)
+ opts, err := transformers.NewGenerateUnixTimestampOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateUnixTimestamp().Generate
+ generate := transformers.NewGenerateUnixTimestamp().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -443,11 +521,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateUsernameConfig:
config := transformerConfig.GetGenerateUsernameConfig()
- opts, err := NewGenerateUsernameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateUsernameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateUsername().Generate
+ generate := transformers.NewGenerateUsername().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -457,11 +535,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateUtctimestampConfig:
config := transformerConfig.GetGenerateUtctimestampConfig()
- opts, err := NewGenerateUTCTimestampOptsFromConfig(config)
+ opts, err := transformers.NewGenerateUTCTimestampOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateUTCTimestamp().Generate
+ generate := transformers.NewGenerateUTCTimestamp().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -471,11 +549,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateUuidConfig:
config := transformerConfig.GetGenerateUuidConfig()
- opts, err := NewGenerateUUIDOptsFromConfig(config)
+ opts, err := transformers.NewGenerateUUIDOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateUUID().Generate
+ generate := transformers.NewGenerateUUID().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -485,11 +563,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateZipcodeConfig:
config := transformerConfig.GetGenerateZipcodeConfig()
- opts, err := NewGenerateZipcodeOptsFromConfig(config)
+ opts, err := transformers.NewGenerateZipcodeOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateZipcode().Generate
+ generate := transformers.NewGenerateZipcode().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -499,11 +577,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformE164PhoneNumberConfig:
config := transformerConfig.GetTransformE164PhoneNumberConfig()
- opts, err := NewTransformE164PhoneNumberOptsFromConfig(config, nil)
+ opts, err := transformers.NewTransformE164PhoneNumberOptsFromConfig(config, nil)
if err != nil {
return nil, err
}
- transform := NewTransformE164PhoneNumber().Transform
+ transform := transformers.NewTransformE164PhoneNumber().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -513,11 +591,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformFirstNameConfig:
config := transformerConfig.GetTransformFirstNameConfig()
- opts, err := NewTransformFirstNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewTransformFirstNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- transform := NewTransformFirstName().Transform
+ transform := transformers.NewTransformFirstName().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -527,11 +605,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformFloat64Config:
config := transformerConfig.GetTransformFloat64Config()
- opts, err := NewTransformFloat64OptsFromConfig(config, nil, nil)
+ opts, err := transformers.NewTransformFloat64OptsFromConfig(config, nil, nil)
if err != nil {
return nil, err
}
- transform := NewTransformFloat64().Transform
+ transform := transformers.NewTransformFloat64().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -541,11 +619,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformInt64PhoneNumberConfig:
config := transformerConfig.GetTransformInt64PhoneNumberConfig()
- opts, err := NewTransformInt64PhoneNumberOptsFromConfig(config)
+ opts, err := transformers.NewTransformInt64PhoneNumberOptsFromConfig(config)
if err != nil {
return nil, err
}
- transform := NewTransformInt64PhoneNumber().Transform
+ transform := transformers.NewTransformInt64PhoneNumber().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -555,11 +633,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformLastNameConfig:
config := transformerConfig.GetTransformLastNameConfig()
- opts, err := NewTransformLastNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewTransformLastNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- transform := NewTransformLastName().Transform
+ transform := transformers.NewTransformLastName().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -569,11 +647,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformPhoneNumberConfig:
config := transformerConfig.GetTransformPhoneNumberConfig()
- opts, err := NewTransformStringPhoneNumberOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewTransformStringPhoneNumberOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- transform := NewTransformStringPhoneNumber().Transform
+ transform := transformers.NewTransformStringPhoneNumber().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -599,11 +677,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_TransformCharacterScrambleConfig:
config := transformerConfig.GetTransformCharacterScrambleConfig()
- opts, err := NewTransformCharacterScrambleOptsFromConfig(config)
+ opts, err := transformers.NewTransformCharacterScrambleOptsFromConfig(config)
if err != nil {
return nil, err
}
- transform := NewTransformCharacterScramble().Transform
+ transform := transformers.NewTransformCharacterScramble().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -613,11 +691,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateCountryConfig:
config := transformerConfig.GetGenerateCountryConfig()
- opts, err := NewGenerateCountryOptsFromConfig(config)
+ opts, err := transformers.NewGenerateCountryOptsFromConfig(config)
if err != nil {
return nil, err
}
- generate := NewGenerateCountry().Generate
+ generate := transformers.NewGenerateCountry().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -656,11 +734,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateBusinessNameConfig:
config := transformerConfig.GetGenerateBusinessNameConfig()
- opts, err := NewGenerateBusinessNameOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateBusinessNameOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateBusinessName().Generate
+ generate := transformers.NewGenerateBusinessName().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -670,11 +748,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
case *mgmtv1alpha1.TransformerConfig_GenerateIpAddressConfig:
config := transformerConfig.GetGenerateIpAddressConfig()
- opts, err := NewGenerateIpAddressOptsFromConfig(config, &maxLength)
+ opts, err := transformers.NewGenerateIpAddressOptsFromConfig(config, &maxLength)
if err != nil {
return nil, err
}
- generate := NewGenerateIpAddress().Generate
+ generate := transformers.NewGenerateIpAddress().Generate
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -683,11 +761,11 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
}, nil
case *mgmtv1alpha1.TransformerConfig_TransformUuidConfig:
config := transformerConfig.GetTransformUuidConfig()
- opts, err := NewTransformUuidOptsFromConfig(config)
+ opts, err := transformers.NewTransformUuidOptsFromConfig(config)
if err != nil {
return nil, err
}
- transform := NewTransformUuid().Transform
+ transform := transformers.NewTransformUuid().Transform
return &TransformerExecutor{
Opts: opts,
Mutate: func(value any, opts any) (any, error) {
@@ -696,6 +774,6 @@ func InitializeTransformerByConfigType(transformerConfig *mgmtv1alpha1.Transform
}, nil
default:
- return nil, fmt.Errorf("unsupported transformer: %v", transformerConfig)
+ return nil, fmt.Errorf("unsupported transformerr: %T", typedCfg)
}
}
diff --git a/worker/pkg/benthos/transformers/transformer_initializer_test.go b/worker/pkg/benthos/transformer_executor/executor_test.go
similarity index 98%
rename from worker/pkg/benthos/transformers/transformer_initializer_test.go
rename to worker/pkg/benthos/transformer_executor/executor_test.go
index 37cdbfdb8d..09eb140d6b 100644
--- a/worker/pkg/benthos/transformers/transformer_initializer_test.go
+++ b/worker/pkg/benthos/transformer_executor/executor_test.go
@@ -1,10 +1,11 @@
-package transformers
+package transformer_executor
import (
"strconv"
"testing"
"time"
+ "github.com/google/uuid"
mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
presidioapi "github.com/nucleuscloud/neosync/internal/ee/presidio"
ee_transformer_fns "github.com/nucleuscloud/neosync/internal/ee/transformers/functions"
@@ -37,6 +38,36 @@ func Test_InitializeTransformerByConfigType(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "A", result)
})
+ t.Run("TransformJavascriptConfig", func(t *testing.T) {
+ config := &mgmtv1alpha1.TransformerConfig{
+ Config: &mgmtv1alpha1.TransformerConfig_TransformJavascriptConfig{
+ TransformJavascriptConfig: &mgmtv1alpha1.TransformJavascript{
+ Code: "return value + ' world';",
+ },
+ },
+ }
+ executor, err := InitializeTransformerByConfigType(config)
+ require.NoError(t, err)
+ require.NotNil(t, executor)
+ result, err := executor.Mutate("hello", nil)
+ require.NoError(t, err)
+ require.Equal(t, "hello world", result)
+ })
+ t.Run("GenerateJavascriptConfig", func(t *testing.T) {
+ config := &mgmtv1alpha1.TransformerConfig{
+ Config: &mgmtv1alpha1.TransformerConfig_GenerateJavascriptConfig{
+ GenerateJavascriptConfig: &mgmtv1alpha1.GenerateJavascript{
+ Code: "return 'hello world';",
+ },
+ },
+ }
+ executor, err := InitializeTransformerByConfigType(config)
+ require.NoError(t, err)
+ require.NotNil(t, executor)
+ result, err := executor.Mutate(nil, nil)
+ require.NoError(t, err)
+ require.Equal(t, "hello world", result)
+ })
t.Run("PassthroughConfig", func(t *testing.T) {
config := &mgmtv1alpha1.TransformerConfig{
Config: &mgmtv1alpha1.TransformerConfig_PassthroughConfig{},
@@ -1713,7 +1744,7 @@ func Test_InitializeTransformerByConfigType(t *testing.T) {
executor, err := InitializeTransformerByConfigType(config)
require.NoError(t, err)
require.NotNil(t, executor)
- originalValue := generateUuid(true)
+ originalValue := uuid.NewString()
result, err := executor.Mutate(originalValue, executor.Opts)
require.NoError(t, err)
require.NotEqual(t, originalValue, result)
@@ -1727,7 +1758,7 @@ func Test_InitializeTransformerByConfigType(t *testing.T) {
executor, err := InitializeTransformerByConfigType(config)
require.NoError(t, err)
require.NotNil(t, executor)
- originalValue := generateUuid(true)
+ originalValue := uuid.NewString()
result, err := executor.Mutate(originalValue, executor.Opts)
require.NoError(t, err)
require.NotEqual(t, originalValue, result)
diff --git a/worker/pkg/benthos/transformer_executor/mock_UserDefinedTransformerResolver.go b/worker/pkg/benthos/transformer_executor/mock_UserDefinedTransformerResolver.go
new file mode 100644
index 0000000000..95dcfee154
--- /dev/null
+++ b/worker/pkg/benthos/transformer_executor/mock_UserDefinedTransformerResolver.go
@@ -0,0 +1,96 @@
+// Code generated by mockery. DO NOT EDIT.
+
+package transformer_executor
+
+import (
+ context "context"
+
+ mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// MockUserDefinedTransformerResolver is an autogenerated mock type for the UserDefinedTransformerResolver type
+type MockUserDefinedTransformerResolver struct {
+ mock.Mock
+}
+
+type MockUserDefinedTransformerResolver_Expecter struct {
+ mock *mock.Mock
+}
+
+func (_m *MockUserDefinedTransformerResolver) EXPECT() *MockUserDefinedTransformerResolver_Expecter {
+ return &MockUserDefinedTransformerResolver_Expecter{mock: &_m.Mock}
+}
+
+// GetUserDefinedTransformer provides a mock function with given fields: ctx, id
+func (_m *MockUserDefinedTransformerResolver) GetUserDefinedTransformer(ctx context.Context, id string) (*mgmtv1alpha1.TransformerConfig, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetUserDefinedTransformer")
+ }
+
+ var r0 *mgmtv1alpha1.TransformerConfig
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) (*mgmtv1alpha1.TransformerConfig, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) *mgmtv1alpha1.TransformerConfig); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*mgmtv1alpha1.TransformerConfig)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserDefinedTransformer'
+type MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call struct {
+ *mock.Call
+}
+
+// GetUserDefinedTransformer is a helper method to define mock.On call
+// - ctx context.Context
+// - id string
+func (_e *MockUserDefinedTransformerResolver_Expecter) GetUserDefinedTransformer(ctx interface{}, id interface{}) *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call {
+ return &MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call{Call: _e.mock.On("GetUserDefinedTransformer", ctx, id)}
+}
+
+func (_c *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call) Run(run func(ctx context.Context, id string)) *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(string))
+ })
+ return _c
+}
+
+func (_c *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call) Return(_a0 *mgmtv1alpha1.TransformerConfig, _a1 error) *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call {
+ _c.Call.Return(_a0, _a1)
+ return _c
+}
+
+func (_c *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call) RunAndReturn(run func(context.Context, string) (*mgmtv1alpha1.TransformerConfig, error)) *MockUserDefinedTransformerResolver_GetUserDefinedTransformer_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
+// NewMockUserDefinedTransformerResolver creates a new instance of MockUserDefinedTransformerResolver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMockUserDefinedTransformerResolver(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *MockUserDefinedTransformerResolver {
+ mock := &MockUserDefinedTransformerResolver{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/worker/pkg/benthos/transformers/benchmarks_test.go b/worker/pkg/benthos/transformers/benchmarks_test.go
new file mode 100644
index 0000000000..8914d6c7c4
--- /dev/null
+++ b/worker/pkg/benthos/transformers/benchmarks_test.go
@@ -0,0 +1,649 @@
+
+// Code generated by Neosync neosync_transformer_generator.go. DO NOT EDIT.
+
+package transformers
+
+import (
+ "testing"
+)
+
+func BenchmarkGenerateBool(b *testing.B) {
+ generator := NewGenerateBool()
+ opts, err := NewGenerateBoolOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateBusinessName(b *testing.B) {
+ generator := NewGenerateBusinessName()
+ opts, err := NewGenerateBusinessNameOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateCardNumber(b *testing.B) {
+ generator := NewGenerateCardNumber()
+ opts, err := NewGenerateCardNumberOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateCategorical(b *testing.B) {
+ generator := NewGenerateCategorical()
+ opts, err := NewGenerateCategoricalOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateCity(b *testing.B) {
+ generator := NewGenerateCity()
+ opts, err := NewGenerateCityOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateCountry(b *testing.B) {
+ generator := NewGenerateCountry()
+ opts, err := NewGenerateCountryOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateEmail(b *testing.B) {
+ generator := NewGenerateEmail()
+ opts, err := NewGenerateEmailOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateFirstName(b *testing.B) {
+ generator := NewGenerateFirstName()
+ opts, err := NewGenerateFirstNameOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateFloat64(b *testing.B) {
+ generator := NewGenerateFloat64()
+ opts, err := NewGenerateFloat64Opts(nil,nil,nil,nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateFullAddress(b *testing.B) {
+ generator := NewGenerateFullAddress()
+ opts, err := NewGenerateFullAddressOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateFullName(b *testing.B) {
+ generator := NewGenerateFullName()
+ opts, err := NewGenerateFullNameOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateGender(b *testing.B) {
+ generator := NewGenerateGender()
+ opts, err := NewGenerateGenderOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateInt64(b *testing.B) {
+ generator := NewGenerateInt64()
+ opts, err := NewGenerateInt64Opts(nil,nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateInt64PhoneNumber(b *testing.B) {
+ generator := NewGenerateInt64PhoneNumber()
+ opts, err := NewGenerateInt64PhoneNumberOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateInternationalPhoneNumber(b *testing.B) {
+ generator := NewGenerateInternationalPhoneNumber()
+ opts, err := NewGenerateInternationalPhoneNumberOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateIpAddress(b *testing.B) {
+ generator := NewGenerateIpAddress()
+ opts, err := NewGenerateIpAddressOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateLastName(b *testing.B) {
+ generator := NewGenerateLastName()
+ opts, err := NewGenerateLastNameOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateRandomString(b *testing.B) {
+ generator := NewGenerateRandomString()
+ opts, err := NewGenerateRandomStringOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateSHA256Hash(b *testing.B) {
+ generator := NewGenerateSHA256Hash()
+ opts, err := NewGenerateSHA256HashOpts()
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateSSN(b *testing.B) {
+ generator := NewGenerateSSN()
+ opts, err := NewGenerateSSNOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateState(b *testing.B) {
+ generator := NewGenerateState()
+ opts, err := NewGenerateStateOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateStreetAddress(b *testing.B) {
+ generator := NewGenerateStreetAddress()
+ opts, err := NewGenerateStreetAddressOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateStringPhoneNumber(b *testing.B) {
+ generator := NewGenerateStringPhoneNumber()
+ opts, err := NewGenerateStringPhoneNumberOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateUnixTimestamp(b *testing.B) {
+ generator := NewGenerateUnixTimestamp()
+ opts, err := NewGenerateUnixTimestampOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateUsername(b *testing.B) {
+ generator := NewGenerateUsername()
+ opts, err := NewGenerateUsernameOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateUTCTimestamp(b *testing.B) {
+ generator := NewGenerateUTCTimestamp()
+ opts, err := NewGenerateUTCTimestampOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateUUID(b *testing.B) {
+ generator := NewGenerateUUID()
+ opts, err := NewGenerateUUIDOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkGenerateZipcode(b *testing.B) {
+ generator := NewGenerateZipcode()
+ opts, err := NewGenerateZipcodeOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := generator.Generate(opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+
+
+func BenchmarkTransformCharacterScramble(b *testing.B) {
+ transformer := NewTransformCharacterScramble()
+ opts, err := NewTransformCharacterScrambleOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformE164PhoneNumber(b *testing.B) {
+ transformer := NewTransformE164PhoneNumber()
+ opts, err := NewTransformE164PhoneNumberOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformEmail(b *testing.B) {
+ transformer := NewTransformEmail()
+ opts, err := NewTransformEmailOpts(nil,nil,nil,nil,nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test@test.com", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformFirstName(b *testing.B) {
+ transformer := NewTransformFirstName()
+ opts, err := NewTransformFirstNameOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformFloat64(b *testing.B) {
+ transformer := NewTransformFloat64()
+ opts, err := NewTransformFloat64Opts(nil,nil,nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform(123.45, opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformFullName(b *testing.B) {
+ transformer := NewTransformFullName()
+ opts, err := NewTransformFullNameOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformInt64(b *testing.B) {
+ transformer := NewTransformInt64()
+ opts, err := NewTransformInt64Opts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform(123456, opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformInt64PhoneNumber(b *testing.B) {
+ transformer := NewTransformInt64PhoneNumber()
+ opts, err := NewTransformInt64PhoneNumberOpts(nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform(123456, opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformLastName(b *testing.B) {
+ transformer := NewTransformLastName()
+ opts, err := NewTransformLastNameOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformString(b *testing.B) {
+ transformer := NewTransformString()
+ opts, err := NewTransformStringOpts(nil,nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformStringPhoneNumber(b *testing.B) {
+ transformer := NewTransformStringPhoneNumber()
+ opts, err := NewTransformStringPhoneNumberOpts(nil,nil,nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+
+func BenchmarkTransformUuid(b *testing.B) {
+ transformer := NewTransformUuid()
+ opts, err := NewTransformUuidOpts(nil,)
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := transformer.Transform("test", opts)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
diff --git a/worker/pkg/benthos/transformers/generate_bool.go b/worker/pkg/benthos/transformers/generate_bool.go
index c7816fa749..3084e3851f 100644
--- a/worker/pkg/benthos/transformers/generate_bool.go
+++ b/worker/pkg/benthos/transformers/generate_bool.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random boolean value.").
+ Category("boolean").
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
err := bloblang.RegisterFunctionV2("generate_bool", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
diff --git a/worker/pkg/benthos/transformers/generate_business_name.go b/worker/pkg/benthos/transformers/generate_business_name.go
index d9b3536a79..621e81528a 100644
--- a/worker/pkg/benthos/transformers/generate_business_name.go
+++ b/worker/pkg/benthos/transformers/generate_business_name.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random business name between 2 and 35 characters long.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_card_number.go b/worker/pkg/benthos/transformers/generate_card_number.go
index c1f6e7796a..7e5326d590 100644
--- a/worker/pkg/benthos/transformers/generate_card_number.go
+++ b/worker/pkg/benthos/transformers/generate_card_number.go
@@ -18,6 +18,7 @@ const defaultIIN = 400000
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a 16 digit card number that is valid by Luhn valid by default.").
+ Category("int64").
Param(bloblang.NewBoolParam("valid_luhn").Default(false).Description("A boolean indicating whether the generated value should pass the Luhn algorithm check.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_categorical.go b/worker/pkg/benthos/transformers/generate_categorical.go
index 5e69035d63..07b61a0f43 100644
--- a/worker/pkg/benthos/transformers/generate_categorical.go
+++ b/worker/pkg/benthos/transformers/generate_categorical.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Randomly selects a value from a defined set of categorical values.").
+ Category("string").
Param(bloblang.NewStringParam("categories").Default("ultimo,proximo,semper").Description("A list of comma-separated string values to randomly select from.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_city.go b/worker/pkg/benthos/transformers/generate_city.go
index f1557bd597..10c09bf591 100644
--- a/worker/pkg/benthos/transformers/generate_city.go
+++ b/worker/pkg/benthos/transformers/generate_city.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Randomly selects a city from a list of predefined US cities.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_city_test.go b/worker/pkg/benthos/transformers/generate_city_test.go
index 50a261b8bc..7a0aae01a8 100644
--- a/worker/pkg/benthos/transformers/generate_city_test.go
+++ b/worker/pkg/benthos/transformers/generate_city_test.go
@@ -53,18 +53,3 @@ func Test_CityTransformer_NoOptions(t *testing.T) {
assert.NotEmptyf(t, res, fmt.Sprintf("The city should be not be empty. This is the error city:%s", res))
}
-
-func BenchmarkGenerateCity(b *testing.B) {
- generator := NewGenerateCity()
- opts, err := NewGenerateCityOptsFromConfig(nil, nil)
- if err != nil {
- b.Fatal(err)
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- _, err := generator.Generate(opts)
- if err != nil {
- b.Fatal(err)
- }
- }
-}
diff --git a/worker/pkg/benthos/transformers/generate_country.go b/worker/pkg/benthos/transformers/generate_country.go
index 3f1f0e7625..e6fdc37910 100644
--- a/worker/pkg/benthos/transformers/generate_country.go
+++ b/worker/pkg/benthos/transformers/generate_country.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().Description("Randomly selects a country and by default, returns it as a 2-letter country code.").
+ Category("string").
Param(bloblang.NewBoolParam("generate_full_name").Default(false).Description("If true returns the full country name instead of the two character country code.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_email.go b/worker/pkg/benthos/transformers/generate_email.go
index 5b1670fc99..04356594b5 100644
--- a/worker/pkg/benthos/transformers/generate_email.go
+++ b/worker/pkg/benthos/transformers/generate_email.go
@@ -34,6 +34,7 @@ func isValidEmailType(emailType string) bool {
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a new randomized email address.").
+ Category("email").
Param(bloblang.NewInt64Param("max_length").Default(100000).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewStringParam("email_type").Default(GenerateEmailType_UuidV4.String()).Description("Specifies the type of email type to generate, with options including `uuidv4`, `fullname`, or `any`.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_email_test.go b/worker/pkg/benthos/transformers/generate_email_test.go
index 208aa2db04..7608f7ef4c 100644
--- a/worker/pkg/benthos/transformers/generate_email_test.go
+++ b/worker/pkg/benthos/transformers/generate_email_test.go
@@ -90,18 +90,3 @@ func Test_RandomEmailTransformer_NoOptions(t *testing.T) {
require.NotEmptyf(t, resStr, fmt.Sprintf("The email should be less than or equal to the max length. This is the error email:%s", res))
}
-
-func BenchmarkGenerateEmail(b *testing.B) {
- generator := NewGenerateEmail()
- opts, err := NewGenerateEmailOptsFromConfig(nil, nil)
- if err != nil {
- b.Fatal(err)
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- _, err := generator.Generate(opts)
- if err != nil {
- b.Fatal(err)
- }
- }
-}
diff --git a/worker/pkg/benthos/transformers/generate_first_name.go b/worker/pkg/benthos/transformers/generate_first_name.go
index 910f44184c..a09e633ed8 100644
--- a/worker/pkg/benthos/transformers/generate_first_name.go
+++ b/worker/pkg/benthos/transformers/generate_first_name.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random first name between 2 and 12 characters long.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_float.go b/worker/pkg/benthos/transformers/generate_float.go
index d1e348bf88..ff55e1502e 100644
--- a/worker/pkg/benthos/transformers/generate_float.go
+++ b/worker/pkg/benthos/transformers/generate_float.go
@@ -17,6 +17,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random floating point number with a max precision of 17. Go float64 adheres to the IEEE 754 standard for double-precision floating-point numbers.").
+ Category("float64").
Param(bloblang.NewBoolParam("randomize_sign").Default(false).Description("A boolean indicating whether the sign of the float should be randomized.")).
Param(bloblang.NewFloat64Param("min").Default(1).Description("Specifies the minimum value for the generated float.")).
Param(bloblang.NewFloat64Param("max").Default(10000).Description("Specifies the maximum value for the generated float")).
diff --git a/worker/pkg/benthos/transformers/generate_full_address.go b/worker/pkg/benthos/transformers/generate_full_address.go
index b94eed4211..4724fd7d8b 100644
--- a/worker/pkg/benthos/transformers/generate_full_address.go
+++ b/worker/pkg/benthos/transformers/generate_full_address.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a randomly selected real full address that exists in the United States.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_full_name.go b/worker/pkg/benthos/transformers/generate_full_name.go
index 9541d1d2db..e5b12132b9 100644
--- a/worker/pkg/benthos/transformers/generate_full_name.go
+++ b/worker/pkg/benthos/transformers/generate_full_name.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a new full name consisting of a first and last name.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_gender.go b/worker/pkg/benthos/transformers/generate_gender.go
index 2c6010aadc..ef02f52e28 100644
--- a/worker/pkg/benthos/transformers/generate_gender.go
+++ b/worker/pkg/benthos/transformers/generate_gender.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Randomly generates one of the following genders: female (f), male (m), undefined (u), nonbinary (n).").
+ Category("string").
Param(bloblang.NewBoolParam("abbreviate").Default(false).Description("Shortens length of generated value to 1.")).
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_int64.go b/worker/pkg/benthos/transformers/generate_int64.go
index 31b0451c40..7d6bea3dc5 100644
--- a/worker/pkg/benthos/transformers/generate_int64.go
+++ b/worker/pkg/benthos/transformers/generate_int64.go
@@ -30,6 +30,7 @@ So we will need to understand what type of column the user is trying to insert t
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random int64 value with a default length of 4.").
+ Category("int64").
Param(bloblang.NewBoolParam("randomize_sign").Default(false).Description("A boolean indicating whether the sign of the float should be randomized.")).
Param(bloblang.NewInt64Param("min").Default(1).Description("Specifies the minimum value for the generated int.")).
Param(bloblang.NewInt64Param("max").Default(10000).Description("Specifies the maximum value for the generated int.")).
diff --git a/worker/pkg/benthos/transformers/generate_int64_phone_number.go b/worker/pkg/benthos/transformers/generate_int64_phone_number.go
index f399d7e919..8097d75fa1 100644
--- a/worker/pkg/benthos/transformers/generate_int64_phone_number.go
+++ b/worker/pkg/benthos/transformers/generate_int64_phone_number.go
@@ -17,6 +17,7 @@ var defaultPhoneNumberLength = int64(10)
func init() {
spec := bloblang.NewPluginSpec().Description("Generates a new int64 phone number with a default length of 10.").
+ Category("int64").
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
err := bloblang.RegisterFunctionV2("generate_int64_phone_number", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
diff --git a/worker/pkg/benthos/transformers/generate_international_phone_number.go b/worker/pkg/benthos/transformers/generate_international_phone_number.go
index 31efdb0ef5..1da0334711 100644
--- a/worker/pkg/benthos/transformers/generate_international_phone_number.go
+++ b/worker/pkg/benthos/transformers/generate_international_phone_number.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
+ Category("string").
Description("Generates a new random international phone number including the + sign and no hyphens.").
Param(bloblang.NewInt64Param("min").Default(9).Description("Specifies the minimum value for the generated phone number.")).
Param(bloblang.NewInt64Param("max").Default(15).Description("Specifies the maximum value for the generated phone number.")).
diff --git a/worker/pkg/benthos/transformers/generate_ip_address.go b/worker/pkg/benthos/transformers/generate_ip_address.go
index 37e67aef86..c08cf78276 100644
--- a/worker/pkg/benthos/transformers/generate_ip_address.go
+++ b/worker/pkg/benthos/transformers/generate_ip_address.go
@@ -44,6 +44,7 @@ var ipv4Ranges = map[IpType]struct {
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates IPv4 or IPv6 addresses with support for different network classes.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100000).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewStringParam("ip_type").Default(string(IpV4_Public)).Description("IP type to generate.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("Optional seed for deterministic generation"))
diff --git a/worker/pkg/benthos/transformers/generate_last_name.go b/worker/pkg/benthos/transformers/generate_last_name.go
index a971ffd74d..f9ed0604bf 100644
--- a/worker/pkg/benthos/transformers/generate_last_name.go
+++ b/worker/pkg/benthos/transformers/generate_last_name.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random last name.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_random_string.go b/worker/pkg/benthos/transformers/generate_random_string.go
index 4f0a4cca0b..efbbcde3ee 100644
--- a/worker/pkg/benthos/transformers/generate_random_string.go
+++ b/worker/pkg/benthos/transformers/generate_random_string.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random string of alphanumeric characters..").
+ Category("string").
Param(bloblang.NewInt64Param("min").Default(1).Description("Specifies the minimum length for the generated string.")).
Param(bloblang.NewInt64Param("max").Default(100).Description("Specifies the maximum length for the generated string.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_sha256hash.go b/worker/pkg/benthos/transformers/generate_sha256hash.go
index 8123c2db37..e5455ddf41 100644
--- a/worker/pkg/benthos/transformers/generate_sha256hash.go
+++ b/worker/pkg/benthos/transformers/generate_sha256hash.go
@@ -13,7 +13,8 @@ import (
// +neosyncTransformerBuilder:generate:generateSHA256Hash
func init() {
- spec := bloblang.NewPluginSpec().Description("Generates a random SHA256 hash and returns it as a string.")
+ spec := bloblang.NewPluginSpec().Description("Generates a random SHA256 hash and returns it as a string.").
+ Category("string")
err := bloblang.RegisterFunctionV2("generate_sha256hash", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
return func() (any, error) {
diff --git a/worker/pkg/benthos/transformers/generate_ssn.go b/worker/pkg/benthos/transformers/generate_ssn.go
index 9eb9eb70b5..99bd4abcf0 100644
--- a/worker/pkg/benthos/transformers/generate_ssn.go
+++ b/worker/pkg/benthos/transformers/generate_ssn.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random social security numbers including the hyphens in the format xxx-xx-xxxx.").
+ Category("string").
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
err := bloblang.RegisterFunctionV2("generate_ssn", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
diff --git a/worker/pkg/benthos/transformers/generate_state.go b/worker/pkg/benthos/transformers/generate_state.go
index f64ae9ee52..af5c5db5ab 100644
--- a/worker/pkg/benthos/transformers/generate_state.go
+++ b/worker/pkg/benthos/transformers/generate_state.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().Description("Randomly selects a US state and by default, returns it as a 2-letter state code.").
+ Category("string").
Param(bloblang.NewBoolParam("generate_full_name").Default(false).Description("If true returns the full state name instead of the two character state code.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_street_address.go b/worker/pkg/benthos/transformers/generate_street_address.go
index 7fa3c056ba..03663fe309 100644
--- a/worker/pkg/benthos/transformers/generate_street_address.go
+++ b/worker/pkg/benthos/transformers/generate_street_address.go
@@ -23,6 +23,7 @@ type Address struct {
func init() {
spec := bloblang.NewPluginSpec().
Description("Randomly generates a street address.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_string_phone_number.go b/worker/pkg/benthos/transformers/generate_string_phone_number.go
index 8d13247ae1..aa213a9912 100644
--- a/worker/pkg/benthos/transformers/generate_string_phone_number.go
+++ b/worker/pkg/benthos/transformers/generate_string_phone_number.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Generates a random 10 digit phone number and returns it as a string with no hyphens.").
+ Category("string").
Param(bloblang.NewInt64Param("min").Default(9).Description("Specifies the minimum length for the generated phone number.")).
Param(bloblang.NewInt64Param("max").Default(15).Description("Specifies the maximum length for the generated phone number.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_unix_timestamp.go b/worker/pkg/benthos/transformers/generate_unix_timestamp.go
index 24c9702f88..1c3b9551b2 100644
--- a/worker/pkg/benthos/transformers/generate_unix_timestamp.go
+++ b/worker/pkg/benthos/transformers/generate_unix_timestamp.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().Description("Randomly generates a Unix timestamp that is in the past.").
+ Category("int64").
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
err := bloblang.RegisterFunctionV2("generate_unixtimestamp", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
diff --git a/worker/pkg/benthos/transformers/generate_username.go b/worker/pkg/benthos/transformers/generate_username.go
index 36d9745564..e9ff119ebf 100644
--- a/worker/pkg/benthos/transformers/generate_username.go
+++ b/worker/pkg/benthos/transformers/generate_username.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Randomly generates a username").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the generated data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/generate_utc_timestamp.go b/worker/pkg/benthos/transformers/generate_utc_timestamp.go
index d751bdda83..93e7fe0368 100644
--- a/worker/pkg/benthos/transformers/generate_utc_timestamp.go
+++ b/worker/pkg/benthos/transformers/generate_utc_timestamp.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().Description("Randomly generates a UTC timestamp.").
+ Category("int64").
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
err := bloblang.RegisterFunctionV2("generate_utctimestamp", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
diff --git a/worker/pkg/benthos/transformers/generate_uuid.go b/worker/pkg/benthos/transformers/generate_uuid.go
index 3ec66c28da..a993a432b0 100644
--- a/worker/pkg/benthos/transformers/generate_uuid.go
+++ b/worker/pkg/benthos/transformers/generate_uuid.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().Description("Generates a new UUIDv4 id.").
+ Category("string").
Param(bloblang.NewBoolParam("include_hyphens").
Default(true).
Description("Determines whether the generated UUID should include hyphens. If set to true, the UUID will be formatted with hyphens (e.g., d853d251-e135-4fe4-a4eb-0aea6bfaf645). If set to false, the hyphens will be omitted (e.g., d853d251e1354fe4a4eb0aea6bfaf645)."))
diff --git a/worker/pkg/benthos/transformers/generate_zipcode.go b/worker/pkg/benthos/transformers/generate_zipcode.go
index 3b107934d9..c63d8b8f72 100644
--- a/worker/pkg/benthos/transformers/generate_zipcode.go
+++ b/worker/pkg/benthos/transformers/generate_zipcode.go
@@ -14,6 +14,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().Description("Generates a randomly selected US zipcode.").
+ Category("string").
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
err := bloblang.RegisterFunctionV2("generate_zipcode", spec, func(args *bloblang.ParsedParams) (bloblang.Function, error) {
diff --git a/worker/pkg/benthos/transformers/generator_utils.go b/worker/pkg/benthos/transformers/generator_utils.go
index 0960af1035..40bc00a8c6 100644
--- a/worker/pkg/benthos/transformers/generator_utils.go
+++ b/worker/pkg/benthos/transformers/generator_utils.go
@@ -49,8 +49,9 @@ type BenthosSpec struct {
BloblangFuncName string
Description string
Example string
+ Category string
Params []*BenthosSpecParam
- Type string
+ Type string // transform or generate
SourceFile string
}
@@ -58,6 +59,7 @@ type ParsedBenthosSpec struct {
Params []*BenthosSpecParam
BloblangFuncName string
SpecDescription string
+ Category string
}
func ExtractBenthosSpec(fileSet *token.FileSet) ([]*BenthosSpec, error) {
@@ -122,6 +124,15 @@ func ParseBloblangSpec(benthosSpec *BenthosSpec) (*ParsedBenthosSpec, error) {
}
}
+ categoryRegex := regexp.MustCompile(`\.Category\("([^"]*)"\)`)
+ var category string
+ if categoryMatches := categoryRegex.FindStringSubmatch(benthosSpecStr); len(categoryMatches) > 0 {
+ category = categoryMatches[1]
+ }
+ if category == "" {
+ return nil, fmt.Errorf("category not found: %s", benthosSpec.SourceFile)
+ }
+
var specDescription string
parsedSpec := strings.Split(benthosSpecStr, ".Param")
for _, line := range parsedSpec {
@@ -165,6 +176,7 @@ func ParseBloblangSpec(benthosSpec *BenthosSpec) (*ParsedBenthosSpec, error) {
BloblangFuncName: bloblangFuncName,
Params: params,
SpecDescription: specDescription,
+ Category: category,
}, nil
}
diff --git a/worker/pkg/benthos/transformers/transform_character_scramble.go b/worker/pkg/benthos/transformers/transform_character_scramble.go
index dd80e75256..bec2fa912d 100644
--- a/worker/pkg/benthos/transformers/transform_character_scramble.go
+++ b/worker/pkg/benthos/transformers/transform_character_scramble.go
@@ -23,6 +23,7 @@ const (
func init() {
spec := bloblang.NewPluginSpec().
Description(`Anonymizes and transforms an existing string value by scrambling the characters while maintaining the format based on a user provided regular expression. Letters will be replaced with letters, numbers with numbers and non-number or letter ASCII characters such as "!&\*" with other characters.`).
+ Category("string").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewStringParam("user_provided_regex").Optional().Description("A custom regular expression. This regex is used to manipulate input data during the transformation process.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/transform_e164_phone_number.go b/worker/pkg/benthos/transformers/transform_e164_phone_number.go
index 47bcde55bd..36cff3b313 100644
--- a/worker/pkg/benthos/transformers/transform_e164_phone_number.go
+++ b/worker/pkg/benthos/transformers/transform_e164_phone_number.go
@@ -16,6 +16,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Transforms an existing E164 formatted phone number.").
+ Category("string").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
Param(bloblang.NewInt64Param("max_length").Default(15).Description("Specifies the maximum length for the transformed data. This field ensures that the output does not exceed a certain number of characters.")).
diff --git a/worker/pkg/benthos/transformers/transform_email.go b/worker/pkg/benthos/transformers/transform_email.go
index b6dfd77fae..3e378694b8 100644
--- a/worker/pkg/benthos/transformers/transform_email.go
+++ b/worker/pkg/benthos/transformers/transform_email.go
@@ -40,6 +40,7 @@ func isValidInvalidEmailAction(action string) bool {
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing email address.").
+ Category("email").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Specifies the maximum length for the transformed data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewBoolParam("preserve_domain").Default(false).Description("A boolean indicating whether the domain part of the email should be preserved.")).
diff --git a/worker/pkg/benthos/transformers/transform_first_name.go b/worker/pkg/benthos/transformers/transform_first_name.go
index 50573ce9ac..99b1e8f0ee 100644
--- a/worker/pkg/benthos/transformers/transform_first_name.go
+++ b/worker/pkg/benthos/transformers/transform_first_name.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Transforms an existing first name").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the transformed data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
diff --git a/worker/pkg/benthos/transformers/transform_float.go b/worker/pkg/benthos/transformers/transform_float.go
index 9730112d28..de55ce5d0c 100644
--- a/worker/pkg/benthos/transformers/transform_float.go
+++ b/worker/pkg/benthos/transformers/transform_float.go
@@ -17,6 +17,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing float value.").
+ Category("float64").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewFloat64Param("randomization_range_min").Default(1).Description("Specifies the minimum value for the range of the float.")).
Param(bloblang.NewFloat64Param("randomization_range_max").Default(10000).Description("Specifies the maximum value for the randomization range of the float.")).
diff --git a/worker/pkg/benthos/transformers/transform_full_name.go b/worker/pkg/benthos/transformers/transform_full_name.go
index 465e934559..3ca4be9842 100644
--- a/worker/pkg/benthos/transformers/transform_full_name.go
+++ b/worker/pkg/benthos/transformers/transform_full_name.go
@@ -16,6 +16,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Transforms an existing full name.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the transformed data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
diff --git a/worker/pkg/benthos/transformers/transform_int64.go b/worker/pkg/benthos/transformers/transform_int64.go
index 24d861d6ca..a2d4304c93 100644
--- a/worker/pkg/benthos/transformers/transform_int64.go
+++ b/worker/pkg/benthos/transformers/transform_int64.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing int64 value.").
+ Category("int64").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewInt64Param("randomization_range_min").Default(1).Description("Specifies the minimum value for the range of the int.")).
Param(bloblang.NewInt64Param("randomization_range_max").Default(10000).Description("Specifies the maximum value for the range of the int.")).
diff --git a/worker/pkg/benthos/transformers/transform_int64_phone_number.go b/worker/pkg/benthos/transformers/transform_int64_phone_number.go
index b0359952f6..1570522281 100644
--- a/worker/pkg/benthos/transformers/transform_int64_phone_number.go
+++ b/worker/pkg/benthos/transformers/transform_int64_phone_number.go
@@ -17,6 +17,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing int64 phone number.").
+ Category("int64").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used to generate deterministic outputs."))
diff --git a/worker/pkg/benthos/transformers/transform_lastname.go b/worker/pkg/benthos/transformers/transform_lastname.go
index 04f71abc9b..bf25aaccd6 100644
--- a/worker/pkg/benthos/transformers/transform_lastname.go
+++ b/worker/pkg/benthos/transformers/transform_lastname.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing last name.").
+ Category("string").
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the transformed data. This field ensures that the output does not exceed a certain number of characters.")).
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
diff --git a/worker/pkg/benthos/transformers/transform_string.go b/worker/pkg/benthos/transformers/transform_string.go
index f18e246c25..89d15f024f 100644
--- a/worker/pkg/benthos/transformers/transform_string.go
+++ b/worker/pkg/benthos/transformers/transform_string.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing string value.").
+ Category("string").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
Param(bloblang.NewInt64Param("min_length").Default(1).Description("Specifies the minimum length of the transformed value.")).
diff --git a/worker/pkg/benthos/transformers/transform_string_phone_number.go b/worker/pkg/benthos/transformers/transform_string_phone_number.go
index fce89e77ca..38b94fcf55 100644
--- a/worker/pkg/benthos/transformers/transform_string_phone_number.go
+++ b/worker/pkg/benthos/transformers/transform_string_phone_number.go
@@ -15,6 +15,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Anonymizes and transforms an existing phone number that is typed as a string.").
+ Category("string").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewBoolParam("preserve_length").Default(false).Description("Whether the original length of the input data should be preserved during transformation. If set to true, the transformation logic will ensure that the output data has the same length as the input data.")).
Param(bloblang.NewInt64Param("max_length").Default(100).Description("Specifies the maximum length for the transformed data. This field ensures that the output does not exceed a certain number of characters.")).
diff --git a/worker/pkg/benthos/transformers/transform_uuid.go b/worker/pkg/benthos/transformers/transform_uuid.go
index a5e4793c51..f03b434675 100644
--- a/worker/pkg/benthos/transformers/transform_uuid.go
+++ b/worker/pkg/benthos/transformers/transform_uuid.go
@@ -17,6 +17,7 @@ import (
func init() {
spec := bloblang.NewPluginSpec().
Description("Transforms an existing UUID to a UUID v5").
+ Category("string").
Param(bloblang.NewAnyParam("value").Optional()).
Param(bloblang.NewInt64Param("seed").Optional().Description("An optional seed value used for generating deterministic transformations."))
diff --git a/worker/pkg/workflows/datasync/activities/run-sql-init-table-stmts/init-statement-builder.go b/worker/pkg/workflows/datasync/activities/run-sql-init-table-stmts/init-statement-builder.go
index fca6f980b2..8ca89c1fc4 100644
--- a/worker/pkg/workflows/datasync/activities/run-sql-init-table-stmts/init-statement-builder.go
+++ b/worker/pkg/workflows/datasync/activities/run-sql-init-table-stmts/init-statement-builder.go
@@ -177,10 +177,15 @@ func (b *initStatementBuilder) RunSqlInitTableStatements(
if block.Label != sqlmanager_postgres.SchemasLabel && block.Label != sqlmanager_postgres.ExtensionsLabel {
return nil, fmt.Errorf("unable to exec pg %s statements: %w", block.Label, err)
}
- initErrors = append(initErrors, &InitSchemaError{
- Statement: strings.Join(block.Statements, "\n"),
- Error: err.Error(),
- })
+ for _, stmt := range block.Statements {
+ err := destdb.Db().Exec(ctx, stmt)
+ if err != nil {
+ initErrors = append(initErrors, &InitSchemaError{
+ Statement: stmt,
+ Error: err.Error(),
+ })
+ }
+ }
}
}
initSchemaRunContext = append(initSchemaRunContext, &InitSchemaRunContext{
@@ -281,10 +286,15 @@ func (b *initStatementBuilder) RunSqlInitTableStatements(
if block.Label != sqlmanager_mysql.SchemasLabel {
return nil, fmt.Errorf("unable to exec mysql %s statements: %w", block.Label, err)
}
- initErrors = append(initErrors, &InitSchemaError{
- Statement: strings.Join(block.Statements, "\n"),
- Error: err.Error(),
- })
+ for _, stmt := range block.Statements {
+ err = destdb.Db().BatchExec(ctx, 1, []string{stmt}, &sqlmanager_shared.BatchExecOpts{})
+ if err != nil {
+ initErrors = append(initErrors, &InitSchemaError{
+ Statement: stmt,
+ Error: err.Error(),
+ })
+ }
+ }
}
}
initSchemaRunContext = append(initSchemaRunContext, &InitSchemaRunContext{