feat(fe2): automations status subscriptions (#1793)
* fe subscriptions working * minor adjustment
This commit is contained in:
committed by
GitHub
parent
79d293e178
commit
eb441d7f4f
@@ -0,0 +1,51 @@
|
||||
import { ApolloCache } from '@apollo/client/core'
|
||||
import { OnModelVersionCardAutomationsStatusUpdatedSubscription } from '~~/lib/common/generated/gql/graphql'
|
||||
import { Get } from 'type-fest'
|
||||
import { onModelVersionCardAutomationsStatusUpdated } from '~~/lib/automations/graphql/subscriptions'
|
||||
import { useApolloClient, useSubscription } from '@vue/apollo-composable'
|
||||
import { useLock } from '~~/lib/common/composables/singleton'
|
||||
|
||||
/**
|
||||
* Track project model/version automations status updates and makes cache updates accordingly.
|
||||
* Optionally you can provide an extra handler to be called when an event is received.
|
||||
*/
|
||||
export const useModelVersionCardAutomationsStatusUpdateTracking = (
|
||||
projectId: MaybeRef<string>,
|
||||
handler?: (
|
||||
data: NonNullable<
|
||||
Get<
|
||||
OnModelVersionCardAutomationsStatusUpdatedSubscription,
|
||||
'projectAutomationsStatusUpdated'
|
||||
>
|
||||
>,
|
||||
cache: ApolloCache<unknown>
|
||||
) => void
|
||||
) => {
|
||||
const { onResult } = useSubscription(
|
||||
onModelVersionCardAutomationsStatusUpdated,
|
||||
() => ({
|
||||
projectId: unref(projectId)
|
||||
})
|
||||
)
|
||||
|
||||
const { hasLock } = useLock(
|
||||
computed(
|
||||
() => `useModelVersionCardAutomationsStatusUpdateTracking-${unref(projectId)}`
|
||||
)
|
||||
)
|
||||
|
||||
const apollo = useApolloClient().client
|
||||
|
||||
onResult((result) => {
|
||||
if (!result.data?.projectAutomationsStatusUpdated || !hasLock.value) return
|
||||
|
||||
// Just by virtue of receiving this event the cache should be updated
|
||||
// In case we need to do any global stuff, feel free to do it below:
|
||||
})
|
||||
|
||||
onResult((result) => {
|
||||
if (!result.data?.projectAutomationsStatusUpdated) return
|
||||
const event = result.data.projectAutomationsStatusUpdated
|
||||
handler?.(event, apollo.cache)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { graphql } from '~~/lib/common/generated/gql'
|
||||
|
||||
export const onModelVersionCardAutomationsStatusUpdated = graphql(`
|
||||
subscription OnModelVersionCardAutomationsStatusUpdated($projectId: String!) {
|
||||
projectAutomationsStatusUpdated(projectId: $projectId) {
|
||||
status {
|
||||
...ModelCardAutomationStatus_AutomationsStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
@@ -70,6 +70,7 @@ const documents = {
|
||||
"\n mutation FinishOnboarding {\n activeUserMutations {\n finishOnboarding\n }\n }\n": types.FinishOnboardingDocument,
|
||||
"\n query AuthServerInfo {\n serverInfo {\n ...AuthStategiesServerInfoFragment\n ...ServerTermsOfServicePrivacyPolicyFragment\n ...AuthRegisterPanelServerInfo\n }\n }\n": types.AuthServerInfoDocument,
|
||||
"\n query AuthorizableAppMetadata($id: String!) {\n app(id: $id) {\n id\n name\n description\n trustByDefault\n redirectUrl\n scopes {\n name\n description\n }\n author {\n name\n id\n avatar\n }\n }\n }\n": types.AuthorizableAppMetadataDocument,
|
||||
"\n subscription OnModelVersionCardAutomationsStatusUpdated($projectId: String!) {\n projectAutomationsStatusUpdated(projectId: $projectId) {\n status {\n ...ModelCardAutomationStatus_AutomationsStatus\n }\n }\n }\n": types.OnModelVersionCardAutomationsStatusUpdatedDocument,
|
||||
"\n query MentionsUserSearch($query: String!, $emailOnly: Boolean = false) {\n userSearch(\n query: $query\n limit: 5\n cursor: null\n archived: false\n emailOnly: $emailOnly\n ) {\n items {\n id\n name\n company\n }\n }\n }\n": types.MentionsUserSearchDocument,
|
||||
"\n query UserSearch($query: String!, $limit: Int, $cursor: String, $archived: Boolean) {\n userSearch(query: $query, limit: $limit, cursor: $cursor, archived: $archived) {\n cursor\n items {\n id\n name\n bio\n company\n avatar\n verified\n role\n }\n }\n }\n": types.UserSearchDocument,
|
||||
"\n query ServerInfoBlobSizeLimit {\n serverInfo {\n blobSizeLimitBytes\n }\n }\n": types.ServerInfoBlobSizeLimitDocument,
|
||||
@@ -396,6 +397,10 @@ export function graphql(source: "\n query AuthServerInfo {\n serverInfo {\n
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query AuthorizableAppMetadata($id: String!) {\n app(id: $id) {\n id\n name\n description\n trustByDefault\n redirectUrl\n scopes {\n name\n description\n }\n author {\n name\n id\n avatar\n }\n }\n }\n"): (typeof documents)["\n query AuthorizableAppMetadata($id: String!) {\n app(id: $id) {\n id\n name\n description\n trustByDefault\n redirectUrl\n scopes {\n name\n description\n }\n author {\n name\n id\n avatar\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n subscription OnModelVersionCardAutomationsStatusUpdated($projectId: String!) {\n projectAutomationsStatusUpdated(projectId: $projectId) {\n status {\n ...ModelCardAutomationStatus_AutomationsStatus\n }\n }\n }\n"): (typeof documents)["\n subscription OnModelVersionCardAutomationsStatusUpdated($projectId: String!) {\n projectAutomationsStatusUpdated(projectId: $projectId) {\n status {\n ...ModelCardAutomationStatus_AutomationsStatus\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -1463,6 +1463,14 @@ export type ProjectWebhooksArgs = {
|
||||
id?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ProjectAutomationsStatusUpdatedMessage = {
|
||||
__typename?: 'ProjectAutomationsStatusUpdatedMessage';
|
||||
model: Model;
|
||||
project: Project;
|
||||
status: AutomationsStatus;
|
||||
version: Version;
|
||||
};
|
||||
|
||||
export type ProjectCollaborator = {
|
||||
__typename?: 'ProjectCollaborator';
|
||||
role: Scalars['String'];
|
||||
@@ -2329,6 +2337,7 @@ export type Subscription = {
|
||||
commitDeleted?: Maybe<Scalars['JSONObject']>;
|
||||
/** Subscribe to commit updated event. */
|
||||
commitUpdated?: Maybe<Scalars['JSONObject']>;
|
||||
projectAutomationsStatusUpdated: ProjectAutomationsStatusUpdatedMessage;
|
||||
/**
|
||||
* Subscribe to updates to resource comments/threads. Optionally specify resource ID string to only receive
|
||||
* updates regarding comments for those resources.
|
||||
@@ -2416,6 +2425,11 @@ export type SubscriptionCommitUpdatedArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectAutomationsStatusUpdatedArgs = {
|
||||
projectId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectCommentsUpdatedArgs = {
|
||||
target: ViewerUpdateTrackingTarget;
|
||||
};
|
||||
@@ -2965,6 +2979,13 @@ export type AuthorizableAppMetadataQueryVariables = Exact<{
|
||||
|
||||
export type AuthorizableAppMetadataQuery = { __typename?: 'Query', app?: { __typename?: 'ServerApp', id: string, name: string, description?: string | null, trustByDefault?: boolean | null, redirectUrl: string, scopes: Array<{ __typename?: 'Scope', name: string, description: string }>, author?: { __typename?: 'AppAuthor', name?: string | null, id?: string | null, avatar?: string | null } | null } | null };
|
||||
|
||||
export type OnModelVersionCardAutomationsStatusUpdatedSubscriptionVariables = Exact<{
|
||||
projectId: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type OnModelVersionCardAutomationsStatusUpdatedSubscription = { __typename?: 'Subscription', projectAutomationsStatusUpdated: { __typename?: 'ProjectAutomationsStatusUpdatedMessage', status: { __typename?: 'AutomationsStatus', id: string, status: AutomationRunStatus, statusMessage?: string | null, automationRuns: Array<{ __typename?: 'AutomationRun', id: string, automationId: string, createdAt: string, status: AutomationRunStatus, functionRuns: Array<{ __typename?: 'AutomationFunctionRun', id: string, functionId: string, elapsed: number, status: AutomationRunStatus, statusMessage?: string | null, contextView?: string | null, resultVersions: Array<{ __typename?: 'Version', id: string }> }> }> } } };
|
||||
|
||||
export type MentionsUserSearchQueryVariables = Exact<{
|
||||
query: Scalars['String'];
|
||||
emailOnly?: InputMaybe<Scalars['Boolean']>;
|
||||
@@ -3586,6 +3607,7 @@ export const CreateOnboardingProjectDocument = {"kind":"Document","definitions":
|
||||
export const FinishOnboardingDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"FinishOnboarding"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUserMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"finishOnboarding"}}]}}]}}]} as unknown as DocumentNode<FinishOnboardingMutation, FinishOnboardingMutationVariables>;
|
||||
export const AuthServerInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AuthServerInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AuthStategiesServerInfoFragment"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerTermsOfServicePrivacyPolicyFragment"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AuthRegisterPanelServerInfo"}}]}}]}},...AuthStategiesServerInfoFragmentFragmentDoc.definitions,...ServerTermsOfServicePrivacyPolicyFragmentFragmentDoc.definitions,...AuthRegisterPanelServerInfoFragmentDoc.definitions]} as unknown as DocumentNode<AuthServerInfoQuery, AuthServerInfoQueryVariables>;
|
||||
export const AuthorizableAppMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AuthorizableAppMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"app"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"trustByDefault"}},{"kind":"Field","name":{"kind":"Name","value":"redirectUrl"}},{"kind":"Field","name":{"kind":"Name","value":"scopes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}}]}}]} as unknown as DocumentNode<AuthorizableAppMetadataQuery, AuthorizableAppMetadataQueryVariables>;
|
||||
export const OnModelVersionCardAutomationsStatusUpdatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnModelVersionCardAutomationsStatusUpdated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectAutomationsStatusUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ModelCardAutomationStatus_AutomationsStatus"}}]}}]}}]}},...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<OnModelVersionCardAutomationsStatusUpdatedSubscription, OnModelVersionCardAutomationsStatusUpdatedSubscriptionVariables>;
|
||||
export const MentionsUserSearchDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MentionsUserSearch"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"query"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"emailOnly"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}},"defaultValue":{"kind":"BooleanValue","value":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userSearch"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"query"},"value":{"kind":"Variable","name":{"kind":"Name","value":"query"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"NullValue"}},{"kind":"Argument","name":{"kind":"Name","value":"archived"},"value":{"kind":"BooleanValue","value":false}},{"kind":"Argument","name":{"kind":"Name","value":"emailOnly"},"value":{"kind":"Variable","name":{"kind":"Name","value":"emailOnly"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"company"}}]}}]}}]}}]} as unknown as DocumentNode<MentionsUserSearchQuery, MentionsUserSearchQueryVariables>;
|
||||
export const UserSearchDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserSearch"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"query"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"archived"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userSearch"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"query"},"value":{"kind":"Variable","name":{"kind":"Name","value":"query"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"archived"},"value":{"kind":"Variable","name":{"kind":"Name","value":"archived"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"bio"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"verified"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]}}]} as unknown as DocumentNode<UserSearchQuery, UserSearchQueryVariables>;
|
||||
export const ServerInfoBlobSizeLimitDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ServerInfoBlobSizeLimit"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"blobSizeLimitBytes"}}]}}]}}]} as unknown as DocumentNode<ServerInfoBlobSizeLimitQuery, ServerInfoBlobSizeLimitQueryVariables>;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MaybeRef } from '@vueuse/core'
|
||||
import { useModelVersionCardAutomationsStatusUpdateTracking } from '~~/lib/automations/composables/automationsStatus'
|
||||
import { useSynchronizedCookie } from '~~/lib/common/composables/reactiveCookie'
|
||||
import { GridListToggleValue } from '~~/lib/layout/helpers/components'
|
||||
import {
|
||||
@@ -60,4 +61,8 @@ export function useGeneralProjectPageUpdateTracking(
|
||||
// Pending model & version update tracking
|
||||
useProjectPendingVersionUpdateTracking(projectId)
|
||||
useProjectPendingModelUpdateTracking(projectId)
|
||||
|
||||
// AUTOMATIONS:
|
||||
// AutomationsStatus update
|
||||
useModelVersionCardAutomationsStatusUpdateTracking(projectId)
|
||||
}
|
||||
|
||||
@@ -117,3 +117,16 @@ type AutomationMutations {
|
||||
extend type Mutation {
|
||||
automationMutations: AutomationMutations!
|
||||
}
|
||||
|
||||
type ProjectAutomationsStatusUpdatedMessage {
|
||||
status: AutomationsStatus!
|
||||
version: Version!
|
||||
model: Model!
|
||||
project: Project!
|
||||
}
|
||||
|
||||
extend type Subscription {
|
||||
projectAutomationsStatusUpdated(
|
||||
projectId: String!
|
||||
): ProjectAutomationsStatusUpdatedMessage!
|
||||
}
|
||||
|
||||
@@ -5,6 +5,12 @@ import {
|
||||
} from '@/modules/automations/services/management'
|
||||
import { formatResults } from '@/modules/automations/services/results'
|
||||
import { Resolvers } from '@/modules/core/graph/generated/graphql'
|
||||
import { getStream } from '@/modules/core/repositories/streams'
|
||||
import {
|
||||
ProjectSubscriptions,
|
||||
filteredSubscribe
|
||||
} from '@/modules/shared/utils/subscriptions'
|
||||
import { ForbiddenError } from 'apollo-server-express'
|
||||
|
||||
export = {
|
||||
Model: {
|
||||
@@ -67,5 +73,28 @@ export = {
|
||||
await upsertModelAutomationRunResult({ userId, input: args.input })
|
||||
return true
|
||||
}
|
||||
},
|
||||
Subscription: {
|
||||
projectAutomationsStatusUpdated: {
|
||||
subscribe: filteredSubscribe(
|
||||
ProjectSubscriptions.ProjectAutomationStatusUpdated,
|
||||
async (payload, variables, context) => {
|
||||
if (payload.projectId !== variables.projectId) return false
|
||||
|
||||
const stream = await getStream({
|
||||
streamId: variables.projectId,
|
||||
userId: context.userId
|
||||
})
|
||||
if (
|
||||
!stream ||
|
||||
(!(stream.isDiscoverable || stream.isPublic) && !stream.role)
|
||||
) {
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
} as Resolvers
|
||||
|
||||
@@ -30,10 +30,14 @@ import { AutomationFunctionRunGraphQLReturn } from '@/modules/automations/helper
|
||||
import { AutomationRunSchema } from '@/modules/automations/helpers/inputTypes'
|
||||
import { StreamNotFoundError } from '@/modules/core/errors/stream'
|
||||
import { BranchNotFoundError } from '@/modules/core/errors/branch'
|
||||
import { getCommits } from '@/modules/core/repositories/commits'
|
||||
import {
|
||||
getCommits,
|
||||
getCommit,
|
||||
getCommitBranch
|
||||
} from '@/modules/core/repositories/commits'
|
||||
import { AutomationNotFoundError } from '@/modules/automations/errors/automations'
|
||||
import { getCommitById } from '@/modules/core/services/commits'
|
||||
import { CommitNotFoundError } from '@/modules/core/errors/commit'
|
||||
import { ProjectSubscriptions, publish } from '@/modules/shared/utils/subscriptions'
|
||||
|
||||
type AutomationRunWithFunctionRunsRecord = AutomationRunRecord & {
|
||||
functionRuns: AutomationFunctionRunRecord[]
|
||||
@@ -76,21 +80,23 @@ export async function upsertModelAutomationRunResult({
|
||||
const automation = await getAutomation(input.automationId)
|
||||
if (!automation) throw new AutomationNotFoundError()
|
||||
|
||||
// authz the current user on the automation
|
||||
const stream = await getStream({
|
||||
userId: userId || undefined,
|
||||
streamId: automation.projectId
|
||||
})
|
||||
const [stream, version, model] = await Promise.all([
|
||||
getStream({
|
||||
userId: userId || undefined,
|
||||
streamId: automation.projectId
|
||||
}),
|
||||
getCommit(validatedInput.versionId, {
|
||||
streamId: automation.projectId
|
||||
}),
|
||||
getCommitBranch(validatedInput.versionId)
|
||||
])
|
||||
|
||||
// this is never going to happen, cause the automation has an FK to the streamId
|
||||
if (!stream) throw new StreamNotFoundError('Project not found')
|
||||
if (stream.role !== Roles.Stream.Owner)
|
||||
throw new ForbiddenError('Only project owners are allowed')
|
||||
|
||||
const version = await getCommitById({
|
||||
streamId: automation.projectId,
|
||||
id: validatedInput.versionId
|
||||
})
|
||||
if (!version) throw new CommitNotFoundError()
|
||||
if (!model) throw new BranchNotFoundError()
|
||||
|
||||
// store the result of the run, if it already exists, patch it
|
||||
const maybeAutomationRun = await getAutomationRun(input.automationRunId)
|
||||
@@ -153,16 +159,23 @@ export async function upsertModelAutomationRunResult({
|
||||
)
|
||||
await insertAutomationFunctionRunResultVersion(validVersionsRecords)
|
||||
|
||||
// 4. publish an event for new automation run creation
|
||||
// 5. publish an event for new run result update
|
||||
// the last two events should be separated.
|
||||
// automate should publish the new run linked to the model / version, with function run results as pending
|
||||
// the running function should only update the function run result
|
||||
// this is, so that FE subscriptions can be added properly.
|
||||
// when a new run is triggered, the frontend should react to that
|
||||
// also for the result of independent function run results.
|
||||
// we're now shortcutting this until the one automation one function barrier is there.
|
||||
// publish(automationRunStatusUpdate, { foo: 'bar' })
|
||||
// Emit subscription
|
||||
const newStatus = await getAutomationsStatus({
|
||||
modelId: version.branchId,
|
||||
projectId: stream.id,
|
||||
versionId: version.id
|
||||
})
|
||||
if (newStatus) {
|
||||
await publish(ProjectSubscriptions.ProjectAutomationStatusUpdated, {
|
||||
projectId: stream.id,
|
||||
projectAutomationsStatusUpdated: {
|
||||
status: newStatus,
|
||||
version,
|
||||
project: stream,
|
||||
model
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const anyFunctionRunsHaveStatus = (
|
||||
|
||||
@@ -1476,6 +1476,14 @@ export type ProjectWebhooksArgs = {
|
||||
id?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ProjectAutomationsStatusUpdatedMessage = {
|
||||
__typename?: 'ProjectAutomationsStatusUpdatedMessage';
|
||||
model: Model;
|
||||
project: Project;
|
||||
status: AutomationsStatus;
|
||||
version: Version;
|
||||
};
|
||||
|
||||
export type ProjectCollaborator = {
|
||||
__typename?: 'ProjectCollaborator';
|
||||
role: Scalars['String'];
|
||||
@@ -2342,6 +2350,7 @@ export type Subscription = {
|
||||
commitDeleted?: Maybe<Scalars['JSONObject']>;
|
||||
/** Subscribe to commit updated event. */
|
||||
commitUpdated?: Maybe<Scalars['JSONObject']>;
|
||||
projectAutomationsStatusUpdated: ProjectAutomationsStatusUpdatedMessage;
|
||||
/**
|
||||
* Subscribe to updates to resource comments/threads. Optionally specify resource ID string to only receive
|
||||
* updates regarding comments for those resources.
|
||||
@@ -2429,6 +2438,11 @@ export type SubscriptionCommitUpdatedArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectAutomationsStatusUpdatedArgs = {
|
||||
projectId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectCommentsUpdatedArgs = {
|
||||
target: ViewerUpdateTrackingTarget;
|
||||
};
|
||||
@@ -2990,6 +3004,7 @@ export type ResolversTypes = {
|
||||
PasswordStrengthCheckResults: ResolverTypeWrapper<PasswordStrengthCheckResults>;
|
||||
PendingStreamCollaborator: ResolverTypeWrapper<PendingStreamCollaboratorGraphQLReturn>;
|
||||
Project: ResolverTypeWrapper<ProjectGraphQLReturn>;
|
||||
ProjectAutomationsStatusUpdatedMessage: ResolverTypeWrapper<Omit<ProjectAutomationsStatusUpdatedMessage, 'model' | 'project' | 'status' | 'version'> & { model: ResolversTypes['Model'], project: ResolversTypes['Project'], status: ResolversTypes['AutomationsStatus'], version: ResolversTypes['Version'] }>;
|
||||
ProjectCollaborator: ResolverTypeWrapper<Omit<ProjectCollaborator, 'user'> & { user: ResolversTypes['LimitedUser'] }>;
|
||||
ProjectCollection: ResolverTypeWrapper<Omit<ProjectCollection, 'items'> & { items: Array<ResolversTypes['Project']> }>;
|
||||
ProjectCommentCollection: ResolverTypeWrapper<Omit<ProjectCommentCollection, 'items'> & { items: Array<ResolversTypes['Comment']> }>;
|
||||
@@ -3160,6 +3175,7 @@ export type ResolversParentTypes = {
|
||||
PasswordStrengthCheckResults: PasswordStrengthCheckResults;
|
||||
PendingStreamCollaborator: PendingStreamCollaboratorGraphQLReturn;
|
||||
Project: ProjectGraphQLReturn;
|
||||
ProjectAutomationsStatusUpdatedMessage: Omit<ProjectAutomationsStatusUpdatedMessage, 'model' | 'project' | 'status' | 'version'> & { model: ResolversParentTypes['Model'], project: ResolversParentTypes['Project'], status: ResolversParentTypes['AutomationsStatus'], version: ResolversParentTypes['Version'] };
|
||||
ProjectCollaborator: Omit<ProjectCollaborator, 'user'> & { user: ResolversParentTypes['LimitedUser'] };
|
||||
ProjectCollection: Omit<ProjectCollection, 'items'> & { items: Array<ResolversParentTypes['Project']> };
|
||||
ProjectCommentCollection: Omit<ProjectCommentCollection, 'items'> & { items: Array<ResolversParentTypes['Comment']> };
|
||||
@@ -3778,6 +3794,14 @@ export type ProjectResolvers<ContextType = GraphQLContext, ParentType extends Re
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ProjectAutomationsStatusUpdatedMessageResolvers<ContextType = GraphQLContext, ParentType extends ResolversParentTypes['ProjectAutomationsStatusUpdatedMessage'] = ResolversParentTypes['ProjectAutomationsStatusUpdatedMessage']> = {
|
||||
model?: Resolver<ResolversTypes['Model'], ParentType, ContextType>;
|
||||
project?: Resolver<ResolversTypes['Project'], ParentType, ContextType>;
|
||||
status?: Resolver<ResolversTypes['AutomationsStatus'], ParentType, ContextType>;
|
||||
version?: Resolver<ResolversTypes['Version'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ProjectCollaboratorResolvers<ContextType = GraphQLContext, ParentType extends ResolversParentTypes['ProjectCollaborator'] = ResolversParentTypes['ProjectCollaborator']> = {
|
||||
role?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
user?: Resolver<ResolversTypes['LimitedUser'], ParentType, ContextType>;
|
||||
@@ -4070,6 +4094,7 @@ export type SubscriptionResolvers<ContextType = GraphQLContext, ParentType exten
|
||||
commitCreated?: SubscriptionResolver<Maybe<ResolversTypes['JSONObject']>, "commitCreated", ParentType, ContextType, RequireFields<SubscriptionCommitCreatedArgs, 'streamId'>>;
|
||||
commitDeleted?: SubscriptionResolver<Maybe<ResolversTypes['JSONObject']>, "commitDeleted", ParentType, ContextType, RequireFields<SubscriptionCommitDeletedArgs, 'streamId'>>;
|
||||
commitUpdated?: SubscriptionResolver<Maybe<ResolversTypes['JSONObject']>, "commitUpdated", ParentType, ContextType, RequireFields<SubscriptionCommitUpdatedArgs, 'streamId'>>;
|
||||
projectAutomationsStatusUpdated?: SubscriptionResolver<ResolversTypes['ProjectAutomationsStatusUpdatedMessage'], "projectAutomationsStatusUpdated", ParentType, ContextType, RequireFields<SubscriptionProjectAutomationsStatusUpdatedArgs, 'projectId'>>;
|
||||
projectCommentsUpdated?: SubscriptionResolver<ResolversTypes['ProjectCommentsUpdatedMessage'], "projectCommentsUpdated", ParentType, ContextType, RequireFields<SubscriptionProjectCommentsUpdatedArgs, 'target'>>;
|
||||
projectModelsUpdated?: SubscriptionResolver<ResolversTypes['ProjectModelsUpdatedMessage'], "projectModelsUpdated", ParentType, ContextType, RequireFields<SubscriptionProjectModelsUpdatedArgs, 'id'>>;
|
||||
projectPendingModelsUpdated?: SubscriptionResolver<ResolversTypes['ProjectPendingModelsUpdatedMessage'], "projectPendingModelsUpdated", ParentType, ContextType, RequireFields<SubscriptionProjectPendingModelsUpdatedArgs, 'id'>>;
|
||||
@@ -4267,6 +4292,7 @@ export type Resolvers<ContextType = GraphQLContext> = {
|
||||
PasswordStrengthCheckResults?: PasswordStrengthCheckResultsResolvers<ContextType>;
|
||||
PendingStreamCollaborator?: PendingStreamCollaboratorResolvers<ContextType>;
|
||||
Project?: ProjectResolvers<ContextType>;
|
||||
ProjectAutomationsStatusUpdatedMessage?: ProjectAutomationsStatusUpdatedMessageResolvers<ContextType>;
|
||||
ProjectCollaborator?: ProjectCollaboratorResolvers<ContextType>;
|
||||
ProjectCollection?: ProjectCollectionResolvers<ContextType>;
|
||||
ProjectCommentCollection?: ProjectCommentCollectionResolvers<ContextType>;
|
||||
|
||||
@@ -38,7 +38,12 @@ export type CommitWithStreamBranchMetadata = CommitRecord & {
|
||||
/**
|
||||
* Get commits with their stream and branch IDs
|
||||
*/
|
||||
export async function getCommits(commitIds: string[]) {
|
||||
export async function getCommits(
|
||||
commitIds: string[],
|
||||
options?: Partial<{ streamId: string }>
|
||||
) {
|
||||
const { streamId } = options || {}
|
||||
|
||||
const q = Commits.knex()
|
||||
.select<CommitWithStreamBranchMetadata[]>(CommitWithStreamBranchMetadataFields)
|
||||
.whereIn(Commits.col.id, commitIds)
|
||||
@@ -46,6 +51,10 @@ export async function getCommits(commitIds: string[]) {
|
||||
.leftJoin(BranchCommits.name, BranchCommits.col.commitId, Commits.col.id)
|
||||
.innerJoin(Branches.name, Branches.col.id, BranchCommits.col.branchId)
|
||||
|
||||
if (streamId) {
|
||||
q.andWhere(StreamCommits.col.streamId, streamId)
|
||||
}
|
||||
|
||||
const rows = await q
|
||||
|
||||
// in case the join tables have multiple values for each commit
|
||||
@@ -55,8 +64,11 @@ export async function getCommits(commitIds: string[]) {
|
||||
return uniqueRows
|
||||
}
|
||||
|
||||
export async function getCommit(commitId: string) {
|
||||
const [commit] = await getCommits([commitId])
|
||||
export async function getCommit(
|
||||
commitId: string,
|
||||
options?: Partial<{ streamId: string }>
|
||||
) {
|
||||
const [commit] = await getCommits([commitId], options)
|
||||
return commit as Optional<typeof commit>
|
||||
}
|
||||
|
||||
|
||||
@@ -1466,6 +1466,14 @@ export type ProjectWebhooksArgs = {
|
||||
id?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ProjectAutomationsStatusUpdatedMessage = {
|
||||
__typename?: 'ProjectAutomationsStatusUpdatedMessage';
|
||||
model: Model;
|
||||
project: Project;
|
||||
status: AutomationsStatus;
|
||||
version: Version;
|
||||
};
|
||||
|
||||
export type ProjectCollaborator = {
|
||||
__typename?: 'ProjectCollaborator';
|
||||
role: Scalars['String'];
|
||||
@@ -2332,6 +2340,7 @@ export type Subscription = {
|
||||
commitDeleted?: Maybe<Scalars['JSONObject']>;
|
||||
/** Subscribe to commit updated event. */
|
||||
commitUpdated?: Maybe<Scalars['JSONObject']>;
|
||||
projectAutomationsStatusUpdated: ProjectAutomationsStatusUpdatedMessage;
|
||||
/**
|
||||
* Subscribe to updates to resource comments/threads. Optionally specify resource ID string to only receive
|
||||
* updates regarding comments for those resources.
|
||||
@@ -2419,6 +2428,11 @@ export type SubscriptionCommitUpdatedArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectAutomationsStatusUpdatedArgs = {
|
||||
projectId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectCommentsUpdatedArgs = {
|
||||
target: ViewerUpdateTrackingTarget;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,9 @@ import Redis from 'ioredis'
|
||||
import { withFilter } from 'graphql-subscriptions'
|
||||
import { GraphQLContext } from '@/modules/shared/helpers/typeHelper'
|
||||
import {
|
||||
AutomationRun,
|
||||
AutomationsStatus,
|
||||
ProjectAutomationsStatusUpdatedMessage,
|
||||
ProjectCommentsUpdatedMessage,
|
||||
ProjectModelsUpdatedMessage,
|
||||
ProjectPendingModelsUpdatedMessage,
|
||||
@@ -12,6 +15,7 @@ import {
|
||||
ProjectUpdatedMessage,
|
||||
ProjectVersionsPreviewGeneratedMessage,
|
||||
ProjectVersionsUpdatedMessage,
|
||||
SubscriptionProjectAutomationsStatusUpdatedArgs,
|
||||
SubscriptionProjectCommentsUpdatedArgs,
|
||||
SubscriptionProjectModelsUpdatedArgs,
|
||||
SubscriptionProjectPendingModelsUpdatedArgs,
|
||||
@@ -33,6 +37,7 @@ import {
|
||||
} from '@/modules/core/helpers/graphTypes'
|
||||
import { CommentGraphQLReturn } from '@/modules/comments/helpers/graphTypes'
|
||||
import { FileUploadGraphQLReturn } from '@/modules/fileuploads/helpers/types'
|
||||
import { AutomationFunctionRunGraphQLReturn } from '@/modules/automations/helpers/graphTypes'
|
||||
|
||||
/**
|
||||
* GraphQL Subscription PubSub instance
|
||||
@@ -82,7 +87,8 @@ export enum ProjectSubscriptions {
|
||||
ProjectModelsUpdated = 'PROJECT_MODELS_UPDATED',
|
||||
ProjectVersionsUpdated = 'PROJECT_VERSIONS_UPDATED',
|
||||
ProjectVersionsPreviewGenerated = 'PROJECT_VERSIONS_PREVIEW_GENERATED',
|
||||
ProjectCommentsUpdated = 'PROJECT_COMMENTS_UPDATED'
|
||||
ProjectCommentsUpdated = 'PROJECT_COMMENTS_UPDATED',
|
||||
ProjectAutomationStatusUpdated = 'PROJECT_AUTOMATION_STATUS_UPDATED'
|
||||
}
|
||||
|
||||
export enum ViewerSubscriptions {
|
||||
@@ -184,6 +190,31 @@ type SubscriptionTypeMap = {
|
||||
}
|
||||
variables: SubscriptionProjectPendingVersionsUpdatedArgs
|
||||
}
|
||||
[ProjectSubscriptions.ProjectAutomationStatusUpdated]: {
|
||||
payload: {
|
||||
projectAutomationsStatusUpdated: Merge<
|
||||
ProjectAutomationsStatusUpdatedMessage,
|
||||
{
|
||||
version: VersionGraphQLReturn
|
||||
model: ModelGraphQLReturn
|
||||
project: ProjectGraphQLReturn
|
||||
status: Merge<
|
||||
AutomationsStatus,
|
||||
{
|
||||
automationRuns: Array<
|
||||
Merge<
|
||||
AutomationRun,
|
||||
{ functionRuns: AutomationFunctionRunGraphQLReturn[] }
|
||||
>
|
||||
>
|
||||
}
|
||||
>
|
||||
}
|
||||
>
|
||||
projectId: string
|
||||
}
|
||||
variables: SubscriptionProjectAutomationsStatusUpdatedArgs
|
||||
}
|
||||
} & { [k in SubscriptionEvent]: { payload: unknown; variables: unknown } }
|
||||
|
||||
type SubscriptionEvent =
|
||||
|
||||
@@ -1466,6 +1466,14 @@ export type ProjectWebhooksArgs = {
|
||||
id?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ProjectAutomationsStatusUpdatedMessage = {
|
||||
__typename?: 'ProjectAutomationsStatusUpdatedMessage';
|
||||
model: Model;
|
||||
project: Project;
|
||||
status: AutomationsStatus;
|
||||
version: Version;
|
||||
};
|
||||
|
||||
export type ProjectCollaborator = {
|
||||
__typename?: 'ProjectCollaborator';
|
||||
role: Scalars['String'];
|
||||
@@ -2332,6 +2340,7 @@ export type Subscription = {
|
||||
commitDeleted?: Maybe<Scalars['JSONObject']>;
|
||||
/** Subscribe to commit updated event. */
|
||||
commitUpdated?: Maybe<Scalars['JSONObject']>;
|
||||
projectAutomationsStatusUpdated: ProjectAutomationsStatusUpdatedMessage;
|
||||
/**
|
||||
* Subscribe to updates to resource comments/threads. Optionally specify resource ID string to only receive
|
||||
* updates regarding comments for those resources.
|
||||
@@ -2419,6 +2428,11 @@ export type SubscriptionCommitUpdatedArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectAutomationsStatusUpdatedArgs = {
|
||||
projectId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type SubscriptionProjectCommentsUpdatedArgs = {
|
||||
target: ViewerUpdateTrackingTarget;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user