Big bump
This commit is contained in:
parent
bfcf7cdfd2
commit
8ba4820654
23 changed files with 301 additions and 270 deletions
|
|
@ -900,7 +900,7 @@ async fn handle_builds_command(matches: &ArgMatches, event_log_uri: &str) -> Res
|
|||
}
|
||||
_ => {
|
||||
println!("Build: {}", detail.build_request_id);
|
||||
println!("Status: {} ({})", detail.status_name, detail.status_code);
|
||||
println!("Status: {} ({})", detail.status.clone().unwrap().name, detail.status.unwrap().code);
|
||||
println!("Requested partitions: {}", detail.requested_partitions.len());
|
||||
println!("Total jobs: {}", detail.total_jobs);
|
||||
println!("Completed jobs: {}", detail.completed_jobs);
|
||||
|
|
@ -958,11 +958,7 @@ async fn handle_builds_command(matches: &ArgMatches, event_log_uri: &str) -> Res
|
|||
println!("\nTimeline ({} events):", detail.timeline.len());
|
||||
for event in detail.timeline {
|
||||
let timestamp = format_timestamp(event.timestamp);
|
||||
let status_info = if let Some(ref status_name) = event.status_name {
|
||||
format!(" -> {}", status_name)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let status_info = event.status.unwrap().name;
|
||||
|
||||
println!(" {} [{}]{} {}", timestamp, event.event_type, status_info, event.message);
|
||||
if let Some(ref reason) = event.cancel_reason {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ genrule(
|
|||
"typescript_generated/src/models/BuildRequest.ts",
|
||||
"typescript_generated/src/models/BuildRequestResponse.ts",
|
||||
"typescript_generated/src/models/BuildSummary.ts",
|
||||
"typescript_generated/src/models/BuildRequestStatus.ts",
|
||||
"typescript_generated/src/models/BuildTimelineEvent.ts",
|
||||
"typescript_generated/src/models/BuildsListApiResponse.ts",
|
||||
"typescript_generated/src/models/BuildsListResponse.ts",
|
||||
|
|
@ -118,6 +119,7 @@ genrule(
|
|||
cp $$TEMP_DIR/src/models/BuildRequest.ts $(location typescript_generated/src/models/BuildRequest.ts)
|
||||
cp $$TEMP_DIR/src/models/BuildRequestResponse.ts $(location typescript_generated/src/models/BuildRequestResponse.ts)
|
||||
cp $$TEMP_DIR/src/models/BuildSummary.ts $(location typescript_generated/src/models/BuildSummary.ts)
|
||||
cp $$TEMP_DIR/src/models/BuildRequestStatus.ts $(location typescript_generated/src/models/BuildRequestStatus.ts)
|
||||
cp $$TEMP_DIR/src/models/BuildTimelineEvent.ts $(location typescript_generated/src/models/BuildTimelineEvent.ts)
|
||||
cp $$TEMP_DIR/src/models/BuildsListApiResponse.ts $(location typescript_generated/src/models/BuildsListApiResponse.ts)
|
||||
cp $$TEMP_DIR/src/models/BuildsListResponse.ts $(location typescript_generated/src/models/BuildsListResponse.ts)
|
||||
|
|
|
|||
|
|
@ -220,8 +220,8 @@ export const RecentActivity: TypedComponent<RecentActivityAttrs> = {
|
|||
}, build.build_request_id)
|
||||
]),
|
||||
m('td', [
|
||||
// KEY FIX: build.status_name is now always a string, prevents runtime errors
|
||||
m(BuildStatusBadge, { status: build.status_name })
|
||||
// KEY FIX: build.status.name is now always a string, prevents runtime errors
|
||||
m(BuildStatusBadge, { status: build.status.name })
|
||||
]),
|
||||
m('td.text-sm.opacity-70', formatTime(build.requested_at)),
|
||||
])
|
||||
|
|
@ -276,7 +276,7 @@ export const RecentActivity: TypedComponent<RecentActivityAttrs> = {
|
|||
}, partition.partition_ref.str)
|
||||
]),
|
||||
m('td', [
|
||||
// KEY FIX: partition.status_name is now always a string, prevents runtime errors
|
||||
// KEY FIX: partition.status.name is now always a string, prevents runtime errors
|
||||
m(PartitionStatusBadge, { status: partition.status_name })
|
||||
]),
|
||||
m('td.text-sm.opacity-70',
|
||||
|
|
@ -402,8 +402,8 @@ export const BuildStatus: TypedComponent<BuildStatusAttrs> = {
|
|||
|
||||
startPolling() {
|
||||
// Use different poll intervals based on build status
|
||||
const isActive = this.data?.status_name === 'EXECUTING' ||
|
||||
this.data?.status_name === 'PLANNING';
|
||||
const isActive = this.data?.status.name === 'EXECUTING' ||
|
||||
this.data?.status.name === 'PLANNING';
|
||||
const interval = isActive ? 2000 : 10000; // 2s for active, 10s for completed
|
||||
|
||||
pollingManager.startPolling(`build-status-${this.buildId}`, () => {
|
||||
|
|
@ -457,7 +457,7 @@ export const BuildStatus: TypedComponent<BuildStatusAttrs> = {
|
|||
{stage: 'Build Requested', time: build.requested_at, icon: '🕚'},
|
||||
...(build.started_at ? [{stage: 'Build Started', time: build.started_at, icon: '▶️'}] : []),
|
||||
// ...(this.data.events as BuildEvent[]).filter(ev => ev.job_event !== null).map((ev) => ({
|
||||
// stage: ev.job_event.status_name, time: ev.timestamp, icon: '🙃'
|
||||
// stage: ev.job_event.status.name, time: ev.timestamp, icon: '🙃'
|
||||
// })),
|
||||
...(build.completed_at ? [{stage: 'Build Completed', time: build.completed_at, icon: '✅'}] : []),
|
||||
];
|
||||
|
|
@ -472,7 +472,7 @@ export const BuildStatus: TypedComponent<BuildStatusAttrs> = {
|
|||
m('.stat.bg-base-100.shadow.rounded-lg.p-4', [
|
||||
m('.stat-title', 'Status'),
|
||||
m('.stat-value.text-2xl', [
|
||||
m(BuildStatusBadge, { status: build.status_name, size: 'lg' })
|
||||
m(BuildStatusBadge, { status: build.status.name, size: 'lg' })
|
||||
])
|
||||
]),
|
||||
m('.stat.bg-base-100.shadow.rounded-lg.p-4', [
|
||||
|
|
@ -518,7 +518,7 @@ export const BuildStatus: TypedComponent<BuildStatusAttrs> = {
|
|||
m('.partition-status.flex.justify-between.items-center', [
|
||||
// CLEAN: Always string status, no nested object access
|
||||
m(PartitionStatusBadge, {
|
||||
status: partitionStatus?.status_name || 'Loading...',
|
||||
status: partitionStatus?.status.name || 'Loading...',
|
||||
size: 'sm'
|
||||
}),
|
||||
partitionStatus?.last_updated ?
|
||||
|
|
@ -905,15 +905,15 @@ export const PartitionStatus: TypedComponent<PartitionStatusAttrs> = {
|
|||
// Update status based on event type
|
||||
if (event.eventType === 'build_request') {
|
||||
if (event.message?.includes('completed') || event.message?.includes('successful')) {
|
||||
build.status_name = 'Completed';
|
||||
build.status.name = 'Completed';
|
||||
build.completedAt = event.timestamp;
|
||||
} else if (event.message?.includes('failed') || event.message?.includes('error')) {
|
||||
build.status_name = 'Failed';
|
||||
build.status.name = 'Failed';
|
||||
build.completedAt = event.timestamp;
|
||||
} else if (event.message?.includes('executing') || event.message?.includes('running')) {
|
||||
build.status_name = 'Executing';
|
||||
build.status.name = 'Executing';
|
||||
} else if (event.message?.includes('planning')) {
|
||||
build.status_name = 'Planning';
|
||||
build.status.name = 'Planning';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1012,7 +1012,7 @@ export const PartitionStatus: TypedComponent<PartitionStatusAttrs> = {
|
|||
]),
|
||||
|
||||
m('div.partition-meta.flex.gap-4.items-center.mb-4', [
|
||||
m(PartitionStatusBadge, { status: this.data?.status_name || 'Unknown', size: 'lg' }),
|
||||
m(PartitionStatusBadge, { status: this.data?.status.name || 'Unknown', size: 'lg' }),
|
||||
this.data?.last_updated ?
|
||||
m('.timestamp.text-sm.opacity-70',
|
||||
`Last updated: ${formatDateTime(this.data.last_updated)}`) : null,
|
||||
|
|
@ -1051,7 +1051,7 @@ export const PartitionStatus: TypedComponent<PartitionStatusAttrs> = {
|
|||
}, build.id)
|
||||
]),
|
||||
m('td', [
|
||||
m(BuildStatusBadge, { status: build.status_name })
|
||||
m(BuildStatusBadge, { status: build.status.name })
|
||||
]),
|
||||
m('td.text-sm.opacity-70',
|
||||
formatDateTime(build.startedAt)),
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ const apiClient = new DefaultApi(apiConfig);
|
|||
function transformBuildSummary(apiResponse: BuildSummary): DashboardBuild {
|
||||
return {
|
||||
build_request_id: apiResponse.build_request_id,
|
||||
status_code: apiResponse.status_code,
|
||||
status_name: apiResponse.status_name,
|
||||
status: apiResponse.status!,
|
||||
requested_partitions: apiResponse.requested_partitions, // Keep as PartitionRef array
|
||||
total_jobs: apiResponse.total_jobs,
|
||||
completed_jobs: apiResponse.completed_jobs,
|
||||
|
|
@ -56,8 +55,7 @@ function transformBuildSummary(apiResponse: BuildSummary): DashboardBuild {
|
|||
function transformBuildDetail(apiResponse: BuildDetailResponse): DashboardBuild {
|
||||
return {
|
||||
build_request_id: apiResponse.build_request_id,
|
||||
status_code: apiResponse.status_code,
|
||||
status_name: apiResponse.status_name,
|
||||
status: apiResponse.status!,
|
||||
requested_partitions: apiResponse.requested_partitions, // Keep as PartitionRef array
|
||||
total_jobs: apiResponse.total_jobs,
|
||||
completed_jobs: apiResponse.completed_jobs,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import {
|
|||
BuildDetailResponse,
|
||||
PartitionSummary,
|
||||
JobSummary,
|
||||
ActivityResponse
|
||||
ActivityResponse,
|
||||
BuildRequestStatus
|
||||
} from '../client/typescript_generated/src/index';
|
||||
|
||||
// Import types directly since we're now in the same ts_project
|
||||
|
|
@ -26,8 +27,7 @@ import {
|
|||
function transformBuildSummary(apiResponse: BuildSummary): DashboardBuild {
|
||||
return {
|
||||
build_request_id: apiResponse.build_request_id,
|
||||
status_code: apiResponse.status_code,
|
||||
status_name: apiResponse.status_name,
|
||||
status: apiResponse.status!,
|
||||
requested_partitions: apiResponse.requested_partitions, // Keep as PartitionRef array
|
||||
total_jobs: apiResponse.total_jobs,
|
||||
completed_jobs: apiResponse.completed_jobs,
|
||||
|
|
@ -44,8 +44,7 @@ function transformBuildSummary(apiResponse: BuildSummary): DashboardBuild {
|
|||
function transformBuildDetail(apiResponse: BuildDetailResponse): DashboardBuild {
|
||||
return {
|
||||
build_request_id: apiResponse.build_request_id,
|
||||
status_code: apiResponse.status_code,
|
||||
status_name: apiResponse.status_name,
|
||||
status: apiResponse.status!,
|
||||
requested_partitions: apiResponse.requested_partitions, // Keep as PartitionRef array
|
||||
total_jobs: apiResponse.total_jobs,
|
||||
completed_jobs: apiResponse.completed_jobs,
|
||||
|
|
@ -98,8 +97,7 @@ function transformActivityResponse(apiResponse: ActivityResponse): DashboardActi
|
|||
// Test Data Mocks
|
||||
const mockBuildSummary: BuildSummary = {
|
||||
build_request_id: 'build-123',
|
||||
status_code: 4, // BUILD_REQUEST_COMPLETED
|
||||
status_name: 'COMPLETED',
|
||||
status: {code: 4, name: 'COMPLETED'},
|
||||
requested_partitions: [{ str: 'partition-1' }, { str: 'partition-2' }],
|
||||
total_jobs: 5,
|
||||
completed_jobs: 5,
|
||||
|
|
@ -151,12 +149,12 @@ o.spec('Transformation Functions', () => {
|
|||
const result = transformBuildSummary(mockBuildSummary);
|
||||
|
||||
// The key fix: status_name should be a string, status_code a number
|
||||
o(typeof result.status_code).equals('number');
|
||||
o(typeof result.status_name).equals('string');
|
||||
o(result.status_name).equals('COMPLETED');
|
||||
o(typeof result.status?.code).equals('number');
|
||||
o(typeof result.status?.name).equals('string');
|
||||
o(result.status.name).equals('COMPLETED');
|
||||
|
||||
// This should not throw (preventing the original runtime error)
|
||||
o(() => result.status_name.toLowerCase()).notThrows('status_name.toLowerCase should work');
|
||||
o(() => result.status.name.toLowerCase()).notThrows('status_name.toLowerCase should work');
|
||||
});
|
||||
|
||||
o('transformBuildSummary handles null optional fields', () => {
|
||||
|
|
@ -219,7 +217,7 @@ o.spec('Transformation Functions', () => {
|
|||
|
||||
// All nested objects should be properly transformed
|
||||
o(result.recent_builds.length).equals(1);
|
||||
o(typeof result.recent_builds[0]?.status_name).equals('string');
|
||||
o(typeof result.recent_builds[0]?.status.name).equals('string');
|
||||
|
||||
o(result.recent_partitions.length).equals(1);
|
||||
o(typeof result.recent_partitions[0]?.partition_ref).equals('object');
|
||||
|
|
@ -233,8 +231,8 @@ o.spec('Transformation Functions', () => {
|
|||
|
||||
// 1. status_name.toLowerCase() - should not crash
|
||||
result.recent_builds.forEach((build: DashboardBuild) => {
|
||||
o(() => build.status_name.toLowerCase()).notThrows('build.status_name.toLowerCase should work');
|
||||
o(build.status_name.toLowerCase()).equals('completed');
|
||||
o(() => build.status.name.toLowerCase()).notThrows('build.status.name.toLowerCase should work');
|
||||
o(build.status.name.toLowerCase()).equals('completed');
|
||||
});
|
||||
|
||||
// 2. partition_ref.str access - should access string property
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import {
|
|||
JobMetricsResponse,
|
||||
JobDailyStats,
|
||||
JobRunSummary,
|
||||
PartitionRef
|
||||
PartitionRef,
|
||||
BuildRequestStatus
|
||||
} from '../client/typescript_generated/src/index';
|
||||
|
||||
// Dashboard-optimized types - canonical frontend types independent of backend schema
|
||||
|
|
@ -19,8 +20,7 @@ import {
|
|||
|
||||
export interface DashboardBuild {
|
||||
build_request_id: string;
|
||||
status_code: number;
|
||||
status_name: string;
|
||||
status: BuildRequestStatus;
|
||||
requested_partitions: PartitionRef[];
|
||||
total_jobs: number;
|
||||
completed_jobs: number;
|
||||
|
|
@ -66,8 +66,7 @@ export interface DashboardActivity {
|
|||
// Dashboard timeline event types for consistent UI handling
|
||||
export interface DashboardBuildTimelineEvent {
|
||||
timestamp: number;
|
||||
status_code: number;
|
||||
status_name: string;
|
||||
status: BuildRequestStatus;
|
||||
message: string;
|
||||
event_type: string;
|
||||
cancel_reason?: string;
|
||||
|
|
@ -75,8 +74,7 @@ export interface DashboardBuildTimelineEvent {
|
|||
|
||||
export interface DashboardPartitionTimelineEvent {
|
||||
timestamp: number;
|
||||
status_code: number;
|
||||
status_name: string;
|
||||
status: BuildRequestStatus;
|
||||
message: string;
|
||||
build_request_id: string;
|
||||
job_run_id?: string;
|
||||
|
|
@ -249,8 +247,8 @@ export function isDashboardActivity(data: any): data is DashboardActivity {
|
|||
export function isDashboardBuild(data: any): data is DashboardBuild {
|
||||
return data &&
|
||||
typeof data.build_request_id === 'string' &&
|
||||
typeof data.status_code === 'number' &&
|
||||
typeof data.status_name === 'string' &&
|
||||
typeof data.status?.code === 'number' &&
|
||||
typeof data.status?.name === 'string' &&
|
||||
typeof data.requested_at === 'number' &&
|
||||
Array.isArray(data.requested_partitions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,9 +239,9 @@ message BuildRequestEvent {
|
|||
// Optional status message
|
||||
string message = 4;
|
||||
// The comment attached to the request - contains arbitrary text
|
||||
string comment = 5;
|
||||
optional string comment = 5;
|
||||
// The id of the want that triggered this build
|
||||
string want_id = 6;
|
||||
optional string want_id = 6;
|
||||
}
|
||||
|
||||
// Partition state change event
|
||||
|
|
@ -301,6 +301,7 @@ message WantEvent {
|
|||
string want_id = 2;
|
||||
// How this want was created
|
||||
WantSource source = 3;
|
||||
string comment = 4;
|
||||
}
|
||||
|
||||
message PartitionWant {
|
||||
|
|
@ -362,6 +363,7 @@ message BuildEvent {
|
|||
// Event metadata
|
||||
string event_id = 1; // UUID for this event
|
||||
int64 timestamp = 2; // Unix timestamp (nanoseconds)
|
||||
optional string build_request_id = 3;
|
||||
|
||||
// Event type and payload (one of)
|
||||
oneof event_type {
|
||||
|
|
@ -530,19 +532,18 @@ message BuildsListResponse {
|
|||
|
||||
message BuildSummary {
|
||||
string build_request_id = 1;
|
||||
BuildRequestStatusCode status_code = 2; // Enum for programmatic use
|
||||
string status_name = 3; // Human-readable string
|
||||
repeated PartitionRef requested_partitions = 4;
|
||||
uint32 total_jobs = 5;
|
||||
uint32 completed_jobs = 6;
|
||||
uint32 failed_jobs = 7;
|
||||
uint32 cancelled_jobs = 8;
|
||||
int64 requested_at = 9;
|
||||
optional int64 started_at = 10;
|
||||
optional int64 completed_at = 11;
|
||||
optional int64 duration_ms = 12;
|
||||
bool cancelled = 13;
|
||||
string comment = 14;
|
||||
BuildRequestStatus status = 2;
|
||||
repeated PartitionRef requested_partitions = 3;
|
||||
uint32 total_jobs = 4;
|
||||
uint32 completed_jobs = 5;
|
||||
uint32 failed_jobs = 6;
|
||||
uint32 cancelled_jobs = 7;
|
||||
int64 requested_at = 8;
|
||||
optional int64 started_at = 9;
|
||||
optional int64 completed_at = 10;
|
||||
optional int64 duration_ms = 11;
|
||||
bool cancelled = 12;
|
||||
optional string comment = 13;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -572,29 +573,27 @@ message BuildDetailRequest {
|
|||
|
||||
message BuildDetailResponse {
|
||||
string build_request_id = 1;
|
||||
BuildRequestStatusCode status_code = 2; // Enum for programmatic use
|
||||
string status_name = 3; // Human-readable string
|
||||
repeated PartitionRef requested_partitions = 4;
|
||||
uint32 total_jobs = 5;
|
||||
uint32 completed_jobs = 6;
|
||||
uint32 failed_jobs = 7;
|
||||
uint32 cancelled_jobs = 8;
|
||||
int64 requested_at = 9;
|
||||
optional int64 started_at = 10;
|
||||
optional int64 completed_at = 11;
|
||||
optional int64 duration_ms = 12;
|
||||
bool cancelled = 13;
|
||||
optional string cancel_reason = 14;
|
||||
repeated BuildTimelineEvent timeline = 15;
|
||||
BuildRequestStatus status = 2;
|
||||
repeated PartitionRef requested_partitions = 3;
|
||||
uint32 total_jobs = 4;
|
||||
uint32 completed_jobs = 5;
|
||||
uint32 failed_jobs = 6;
|
||||
uint32 cancelled_jobs = 7;
|
||||
int64 requested_at = 8;
|
||||
optional int64 started_at = 9;
|
||||
optional int64 completed_at = 10;
|
||||
optional int64 duration_ms = 11;
|
||||
bool cancelled = 12;
|
||||
optional string cancel_reason = 13;
|
||||
repeated BuildTimelineEvent timeline = 14;
|
||||
}
|
||||
|
||||
message BuildTimelineEvent {
|
||||
int64 timestamp = 1;
|
||||
optional BuildRequestStatusCode status_code = 2; // Enum for programmatic use
|
||||
optional string status_name = 3; // Human-readable string
|
||||
string message = 4;
|
||||
string event_type = 5;
|
||||
optional string cancel_reason = 6;
|
||||
optional BuildRequestStatus status = 2;
|
||||
string message = 3;
|
||||
string event_type = 4;
|
||||
optional string cancel_reason = 5;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -204,6 +204,8 @@ impl MockBuildEventLog {
|
|||
Some(crate::build_event::EventType::PartitionInvalidationEvent(_)) => "partition_invalidation",
|
||||
Some(crate::build_event::EventType::JobRunCancelEvent(_)) => "job_run_cancel",
|
||||
Some(crate::build_event::EventType::BuildCancelEvent(_)) => "build_cancel",
|
||||
Some(crate::build_event::EventType::WantEvent(_)) => "want",
|
||||
Some(crate::build_event::EventType::TaintEvent(_)) => "taint",
|
||||
None => "unknown",
|
||||
},
|
||||
event_data
|
||||
|
|
@ -220,7 +222,7 @@ impl MockBuildEventLog {
|
|||
"INSERT INTO build_request_events (event_id, status, requested_partitions, message) VALUES (?1, ?2, ?3, ?4)",
|
||||
rusqlite::params![
|
||||
event.event_id,
|
||||
br_event.status_code.to_string(),
|
||||
br_event.clone().status.unwrap().code.to_string(),
|
||||
partitions_json,
|
||||
br_event.message
|
||||
],
|
||||
|
|
@ -379,12 +381,13 @@ pub mod test_events {
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id: build_request_id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
||||
build_request_id,
|
||||
event_type: Some(build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestReceived as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestReceived.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
requested_partitions: partitions,
|
||||
message: "Build request received".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
|
@ -398,12 +401,13 @@ pub mod test_events {
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id: build_request_id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
||||
build_request_id,
|
||||
event_type: Some(build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: status as i32,
|
||||
status_name: status.to_display_string(),
|
||||
status: Some(status.clone()),
|
||||
requested_partitions: partitions,
|
||||
message: format!("Build request status: {:?}", status),
|
||||
message: format!("Build request status: {:?}", status.name),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
|
@ -418,7 +422,7 @@ pub mod test_events {
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id: build_request_id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
||||
build_request_id,
|
||||
event_type: Some(build_event::EventType::PartitionEvent(PartitionEvent {
|
||||
partition_ref: Some(partition_ref),
|
||||
status_code: status as i32,
|
||||
|
|
@ -440,7 +444,7 @@ pub mod test_events {
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id: build_request_id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
||||
build_request_id,
|
||||
event_type: Some(build_event::EventType::JobEvent(JobEvent {
|
||||
job_run_id: job_run_id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
||||
job_label: Some(job_label),
|
||||
|
|
@ -563,9 +567,10 @@ impl BELStorage for MockBELStorage {
|
|||
|
||||
// Apply filtering based on EventFilter
|
||||
events.retain(|event| {
|
||||
|
||||
// Filter by build request IDs if specified
|
||||
if !filter.build_request_ids.is_empty() {
|
||||
if !filter.build_request_ids.contains(&event.build_request_id) {
|
||||
if !filter.build_request_ids.contains(&event.build_request_id.clone().unwrap()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ pub fn create_build_event(
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id.clone()),
|
||||
event_type: Some(event_type),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,15 +38,16 @@ impl BELQueryEngine {
|
|||
};
|
||||
|
||||
let events = self.storage.list_events(0, filter).await?;
|
||||
let mut active_builds = Vec::new();
|
||||
let mut build_states: HashMap<String, BuildRequestStatus> = HashMap::new();
|
||||
let mut active_builds: Vec<String> = Vec::new();
|
||||
let mut build_states: HashMap<String, BuildRequestStatusCode> = HashMap::new();
|
||||
|
||||
// Process events chronologically to track build states
|
||||
for event in events.events {
|
||||
let build_request_id = event.build_request_id.clone().unwrap();
|
||||
match &event.event_type {
|
||||
Some(crate::build_event::EventType::BuildRequestEvent(br_event)) => {
|
||||
if let Ok(status) = BuildRequestStatus::try_from(br_event.status_code) {
|
||||
build_states.insert(event.build_request_id.clone(), status);
|
||||
if let Ok(code) = BuildRequestStatusCode::try_from(br_event.clone().status.unwrap().code) {
|
||||
build_states.insert(build_request_id.clone(), code);
|
||||
}
|
||||
}
|
||||
Some(crate::build_event::EventType::PartitionEvent(p_event)) => {
|
||||
|
|
@ -56,15 +57,15 @@ impl BELQueryEngine {
|
|||
if let Ok(status) = PartitionStatus::try_from(p_event.status_code) {
|
||||
if matches!(status, PartitionStatus::PartitionBuilding | PartitionStatus::PartitionAnalyzed) {
|
||||
// Check if the build request is still active
|
||||
if let Some(build_status) = build_states.get(&event.build_request_id) {
|
||||
if let Some(build_status) = build_states.get(&build_request_id) {
|
||||
if matches!(build_status,
|
||||
BuildRequestStatus::BuildRequestReceived |
|
||||
BuildRequestStatus::BuildRequestPlanning |
|
||||
BuildRequestStatus::BuildRequestExecuting |
|
||||
BuildRequestStatus::BuildRequestAnalysisCompleted
|
||||
BuildRequestStatusCode::BuildRequestReceived |
|
||||
BuildRequestStatusCode::BuildRequestPlanning |
|
||||
BuildRequestStatusCode::BuildRequestExecuting |
|
||||
BuildRequestStatusCode::BuildRequestAnalysisCompleted
|
||||
) {
|
||||
if !active_builds.contains(&event.build_request_id) {
|
||||
active_builds.push(event.build_request_id.clone());
|
||||
if !active_builds.contains(&build_request_id) {
|
||||
active_builds.push(build_request_id.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,12 +98,12 @@ impl BELQueryEngine {
|
|||
return Err(BuildEventLogError::QueryError(format!("Build request '{}' not found", build_id)));
|
||||
}
|
||||
|
||||
let mut status = BuildRequestStatus::BuildRequestUnknown;
|
||||
let mut status = BuildRequestStatusCode::BuildRequestUnknown.status();
|
||||
let mut requested_partitions = Vec::new();
|
||||
let mut created_at = 0i64;
|
||||
let mut updated_at = 0i64;
|
||||
|
||||
for event in events.events {
|
||||
for event in events.events.iter().filter(|event| event.build_request_id.is_some()) {
|
||||
if event.timestamp > 0 {
|
||||
if created_at == 0 || event.timestamp < created_at {
|
||||
created_at = event.timestamp;
|
||||
|
|
@ -113,7 +114,7 @@ impl BELQueryEngine {
|
|||
}
|
||||
|
||||
if let Some(crate::build_event::EventType::BuildRequestEvent(br_event)) = &event.event_type {
|
||||
if let Ok(event_status) = BuildRequestStatus::try_from(br_event.status_code) {
|
||||
if let Ok(event_status) = BuildRequestStatus::try_from(br_event.status.clone().unwrap()) {
|
||||
status = event_status;
|
||||
}
|
||||
if !br_event.requested_partitions.is_empty() {
|
||||
|
|
@ -148,20 +149,20 @@ impl BELQueryEngine {
|
|||
let mut build_summaries: HashMap<String, BuildRequestSummary> = HashMap::new();
|
||||
|
||||
// Aggregate by build request ID
|
||||
for event in events.events {
|
||||
for event in events.events.iter().filter(|event| event.build_request_id.is_some()) {
|
||||
if let Some(crate::build_event::EventType::BuildRequestEvent(br_event)) = &event.event_type {
|
||||
let build_id = &event.build_request_id;
|
||||
let build_id = &event.build_request_id.clone().unwrap();
|
||||
let entry = build_summaries.entry(build_id.clone()).or_insert_with(|| {
|
||||
BuildRequestSummary {
|
||||
build_request_id: build_id.clone(),
|
||||
status: BuildRequestStatus::BuildRequestUnknown,
|
||||
status: BuildRequestStatusCode::BuildRequestUnknown.status(),
|
||||
requested_partitions: Vec::new(),
|
||||
created_at: event.timestamp,
|
||||
updated_at: event.timestamp,
|
||||
}
|
||||
});
|
||||
|
||||
if let Ok(status) = BuildRequestStatus::try_from(br_event.status_code) {
|
||||
if let Ok(status) = BuildRequestStatus::try_from(br_event.status.clone().unwrap()) {
|
||||
entry.status = status;
|
||||
}
|
||||
entry.updated_at = event.timestamp.max(entry.updated_at);
|
||||
|
|
@ -179,8 +180,8 @@ impl BELQueryEngine {
|
|||
// Apply status filter if provided
|
||||
if let Some(status_filter) = &request.status_filter {
|
||||
if let Ok(filter_status) = status_filter.parse::<i32>() {
|
||||
if let Ok(status) = BuildRequestStatus::try_from(filter_status) {
|
||||
builds.retain(|b| b.status == status);
|
||||
if let Ok(status) = BuildRequestStatusCode::try_from(filter_status) {
|
||||
builds.retain(|b| b.status.code == status as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -194,8 +195,7 @@ impl BELQueryEngine {
|
|||
.take(limit)
|
||||
.map(|summary| BuildSummary {
|
||||
build_request_id: summary.build_request_id,
|
||||
status_code: summary.status as i32,
|
||||
status_name: summary.status.to_display_string(),
|
||||
status: Some(summary.status),
|
||||
requested_partitions: summary.requested_partitions.into_iter()
|
||||
.map(|s| PartitionRef { str: s })
|
||||
.collect(),
|
||||
|
|
@ -208,6 +208,7 @@ impl BELQueryEngine {
|
|||
completed_at: None, // TODO: Implement
|
||||
duration_ms: None, // TODO: Implement
|
||||
cancelled: false, // TODO: Implement
|
||||
comment: None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -228,18 +229,18 @@ impl BELQueryEngine {
|
|||
|
||||
let active_builds_count = builds_response.builds.iter()
|
||||
.filter(|b| matches!(
|
||||
BuildRequestStatus::try_from(b.status_code).unwrap_or(BuildRequestStatus::BuildRequestUnknown),
|
||||
BuildRequestStatus::BuildRequestReceived |
|
||||
BuildRequestStatus::BuildRequestPlanning |
|
||||
BuildRequestStatus::BuildRequestExecuting |
|
||||
BuildRequestStatus::BuildRequestAnalysisCompleted
|
||||
BuildRequestStatusCode::try_from(b.status.clone().unwrap().code).unwrap_or(BuildRequestStatusCode::BuildRequestUnknown),
|
||||
BuildRequestStatusCode::BuildRequestReceived |
|
||||
BuildRequestStatusCode::BuildRequestPlanning |
|
||||
BuildRequestStatusCode::BuildRequestExecuting |
|
||||
BuildRequestStatusCode::BuildRequestAnalysisCompleted
|
||||
))
|
||||
.count() as u32;
|
||||
|
||||
let recent_builds = builds_response.builds.into_iter()
|
||||
.map(|b| BuildRequestSummary {
|
||||
build_request_id: b.build_request_id,
|
||||
status: BuildRequestStatus::try_from(b.status_code).unwrap_or(BuildRequestStatus::BuildRequestUnknown),
|
||||
status: b.status.unwrap_or(BuildRequestStatusCode::BuildRequestUnknown.status()),
|
||||
requested_partitions: b.requested_partitions.into_iter().map(|p| p.str).collect(),
|
||||
created_at: b.requested_at,
|
||||
updated_at: b.completed_at.unwrap_or(b.requested_at),
|
||||
|
|
@ -299,7 +300,7 @@ impl BELQueryEngine {
|
|||
if partition_event_ref.str == partition_ref {
|
||||
if let Ok(status) = PartitionStatus::try_from(p_event.status_code) {
|
||||
if status == PartitionStatus::PartitionAvailable && event.timestamp >= latest_timestamp {
|
||||
latest_available_build_id = Some(event.build_request_id.clone());
|
||||
latest_available_build_id = event.build_request_id.clone();
|
||||
latest_timestamp = event.timestamp;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ impl EventWriter {
|
|||
let event = create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestReceived as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestReceived.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
requested_partitions,
|
||||
message: "Build request received".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -57,10 +58,11 @@ impl EventWriter {
|
|||
let event = create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: status as i32,
|
||||
status_name: status.to_display_string(),
|
||||
status: Some(status),
|
||||
requested_partitions: vec![],
|
||||
message,
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -80,10 +82,11 @@ impl EventWriter {
|
|||
let event = create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: status as i32,
|
||||
status_name: status.to_display_string(),
|
||||
status: Some(status),
|
||||
requested_partitions,
|
||||
message,
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -104,7 +107,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::PartitionEvent(PartitionEvent {
|
||||
partition_ref: Some(partition_ref),
|
||||
status_code: status as i32,
|
||||
|
|
@ -136,7 +139,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::PartitionInvalidationEvent(
|
||||
PartitionInvalidationEvent {
|
||||
partition_ref: Some(partition_ref),
|
||||
|
|
@ -162,7 +165,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::JobEvent(JobEvent {
|
||||
job_run_id,
|
||||
job_label: Some(job_label),
|
||||
|
|
@ -194,7 +197,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::JobEvent(JobEvent {
|
||||
job_run_id,
|
||||
job_label: Some(job_label),
|
||||
|
|
@ -256,7 +259,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::JobRunCancelEvent(JobRunCancelEvent {
|
||||
job_run_id,
|
||||
reason,
|
||||
|
|
@ -285,22 +288,22 @@ impl EventWriter {
|
|||
let latest_status = build_events.iter()
|
||||
.rev()
|
||||
.find_map(|e| match &e.event_type {
|
||||
Some(build_event::EventType::BuildRequestEvent(br)) => Some(br.status_code),
|
||||
Some(build_event::EventType::BuildRequestEvent(br)) => Some(br.clone().status.unwrap().code),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
match latest_status {
|
||||
Some(status) if status == BuildRequestStatus::BuildRequestCompleted as i32 => {
|
||||
Some(status) if status == BuildRequestStatusCode::BuildRequestCompleted as i32 => {
|
||||
return Err(BuildEventLogError::QueryError(
|
||||
format!("Cannot cancel completed build: {}", build_request_id)
|
||||
));
|
||||
}
|
||||
Some(status) if status == BuildRequestStatus::BuildRequestFailed as i32 => {
|
||||
Some(status) if status == BuildRequestStatusCode::BuildRequestFailed as i32 => {
|
||||
return Err(BuildEventLogError::QueryError(
|
||||
format!("Cannot cancel failed build: {}", build_request_id)
|
||||
));
|
||||
}
|
||||
Some(status) if status == BuildRequestStatus::BuildRequestCancelled as i32 => {
|
||||
Some(status) if status == BuildRequestStatusCode::BuildRequestCancelled as i32 => {
|
||||
return Err(BuildEventLogError::QueryError(
|
||||
format!("Build already cancelled: {}", build_request_id)
|
||||
));
|
||||
|
|
@ -311,7 +314,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id: build_request_id.clone(),
|
||||
build_request_id: Some(build_request_id.clone()),
|
||||
event_type: Some(build_event::EventType::BuildCancelEvent(BuildCancelEvent {
|
||||
reason,
|
||||
})),
|
||||
|
|
@ -322,7 +325,7 @@ impl EventWriter {
|
|||
// Also emit a build request status update
|
||||
self.update_build_status(
|
||||
build_request_id,
|
||||
BuildRequestStatus::BuildRequestCancelled,
|
||||
BuildRequestStatusCode::BuildRequestCancelled.status(),
|
||||
"Build cancelled by user".to_string(),
|
||||
).await
|
||||
}
|
||||
|
|
@ -361,7 +364,7 @@ impl EventWriter {
|
|||
let event = BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::JobGraphEvent(JobGraphEvent {
|
||||
job_graph: Some(job_graph),
|
||||
message,
|
||||
|
|
@ -391,19 +394,19 @@ mod tests {
|
|||
// Test status updates
|
||||
writer.update_build_status(
|
||||
build_id.clone(),
|
||||
BuildRequestStatus::BuildRequestPlanning,
|
||||
BuildRequestStatusCode::BuildRequestPlanning.status(),
|
||||
"Starting planning".to_string(),
|
||||
).await.unwrap();
|
||||
|
||||
writer.update_build_status(
|
||||
build_id.clone(),
|
||||
BuildRequestStatus::BuildRequestExecuting,
|
||||
BuildRequestStatusCode::BuildRequestExecuting.status(),
|
||||
"Starting execution".to_string(),
|
||||
).await.unwrap();
|
||||
|
||||
writer.update_build_status(
|
||||
build_id.clone(),
|
||||
BuildRequestStatus::BuildRequestCompleted,
|
||||
BuildRequestStatusCode::BuildRequestCompleted.status(),
|
||||
"Build completed successfully".to_string(),
|
||||
).await.unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,9 +107,8 @@ mod format_consistency_tests {
|
|||
assert_eq!(JobStatus::from_display_string("completed"), Some(job_status));
|
||||
|
||||
// Test BuildRequestStatus conversions
|
||||
let build_status = BuildRequestStatus::BuildRequestCompleted;
|
||||
assert_eq!(build_status.to_display_string(), "completed");
|
||||
assert_eq!(BuildRequestStatus::from_display_string("completed"), Some(build_status));
|
||||
let build_status = BuildRequestStatusCode::BuildRequestCompleted.status();
|
||||
assert_eq!(build_status.name, "completed");
|
||||
|
||||
// Test invalid conversions
|
||||
assert_eq!(PartitionStatus::from_display_string("invalid"), None);
|
||||
|
|
|
|||
|
|
@ -203,10 +203,11 @@ async fn plan(
|
|||
let event = create_build_event(
|
||||
build_request_id.to_string(),
|
||||
crate::build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestReceived as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestReceived.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
requested_partitions: output_refs.iter().map(|s| PartitionRef { str: s.clone() }).collect(),
|
||||
message: "Analysis started".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
if let Err(e) = query_engine_ref.append_event(event).await {
|
||||
|
|
@ -264,10 +265,11 @@ async fn plan(
|
|||
let event = create_build_event(
|
||||
build_request_id.to_string(),
|
||||
crate::build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestPlanning as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestPlanning.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestPlanning.status()),
|
||||
requested_partitions: output_refs.iter().map(|s| PartitionRef { str: s.clone() }).collect(),
|
||||
message: "Graph analysis in progress".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
if let Err(e) = query_engine_ref.append_event(event).await {
|
||||
|
|
@ -334,10 +336,11 @@ async fn plan(
|
|||
let event = create_build_event(
|
||||
build_request_id.to_string(),
|
||||
crate::build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestAnalysisCompleted as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestAnalysisCompleted.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestAnalysisCompleted.status()),
|
||||
requested_partitions: output_refs.iter().map(|s| PartitionRef { str: s.clone() }).collect(),
|
||||
message: format!("Analysis completed successfully, {} tasks planned", nodes.len()),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
if let Err(e) = query_engine.append_event(event).await {
|
||||
|
|
@ -376,10 +379,11 @@ async fn plan(
|
|||
let event = create_build_event(
|
||||
build_request_id.to_string(),
|
||||
crate::build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestFailed as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestFailed.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestFailed.status()),
|
||||
requested_partitions: output_refs.iter().map(|s| PartitionRef { str: s.clone() }).collect(),
|
||||
message: "No jobs found for requested partitions".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
if let Err(e) = query_engine.append_event(event).await {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use databuild::{JobGraph, Task, JobStatus, BuildRequestStatus, PartitionStatus, BuildRequestEvent, JobEvent, PartitionEvent, PartitionRef};
|
||||
use databuild::{JobGraph, Task, JobStatus, BuildRequestStatus, BuildRequestStatusCode, PartitionStatus, BuildRequestEvent, JobEvent, PartitionEvent, PartitionRef};
|
||||
use databuild::event_log::{create_bel_query_engine, create_build_event};
|
||||
use databuild::build_event::EventType;
|
||||
use databuild::log_collector::{LogCollector, LogCollectorError};
|
||||
|
|
@ -460,10 +460,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let event = create_build_event(
|
||||
build_request_id.clone(),
|
||||
EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestExecuting as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestExecuting.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestExecuting.status()),
|
||||
requested_partitions: graph.outputs.clone(),
|
||||
message: format!("Starting execution of {} jobs", graph.nodes.len()),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
if let Err(e) = query_engine.append_event(event).await {
|
||||
|
|
@ -787,18 +788,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
// Log final build request status (existing detailed event)
|
||||
if let Some(ref query_engine) = build_event_log {
|
||||
let final_status = if failure_count > 0 || fail_fast_triggered {
|
||||
BuildRequestStatus::BuildRequestFailed
|
||||
BuildRequestStatusCode::BuildRequestFailed
|
||||
} else {
|
||||
BuildRequestStatus::BuildRequestCompleted
|
||||
BuildRequestStatusCode::BuildRequestCompleted
|
||||
};
|
||||
|
||||
let event = create_build_event(
|
||||
build_request_id.clone(),
|
||||
EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: final_status as i32,
|
||||
status_name: final_status.to_display_string(),
|
||||
status: Some(final_status.status()),
|
||||
requested_partitions: graph.outputs.clone(),
|
||||
message: format!("Execution completed: {} succeeded, {} failed", success_count, failure_count),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
if let Err(e) = query_engine.append_event(event).await {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ pub fn create_build_request_received_event(
|
|||
create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestReceived as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestReceived.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
requested_partitions,
|
||||
message: "Build request received".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
@ -24,10 +25,11 @@ pub fn create_build_planning_started_event(
|
|||
create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestPlanning as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestPlanning.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestPlanning.status()),
|
||||
requested_partitions: vec![],
|
||||
message: "Starting build planning".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
@ -38,10 +40,11 @@ pub fn create_build_execution_started_event(
|
|||
create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestExecuting as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestExecuting.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestExecuting.status()),
|
||||
requested_partitions: vec![],
|
||||
message: "Starting build execution".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
@ -63,17 +66,18 @@ pub fn create_build_completed_event(
|
|||
};
|
||||
|
||||
let status = match result {
|
||||
super::BuildResult::Success { .. } => BuildRequestStatus::BuildRequestCompleted,
|
||||
super::BuildResult::Failed { .. } | super::BuildResult::FailFast { .. } => BuildRequestStatus::BuildRequestFailed,
|
||||
super::BuildResult::Success { .. } => BuildRequestStatusCode::BuildRequestCompleted.status(),
|
||||
super::BuildResult::Failed { .. } | super::BuildResult::FailFast { .. } => BuildRequestStatusCode::BuildRequestFailed.status(),
|
||||
};
|
||||
|
||||
create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: status as i32,
|
||||
status_name: status.to_display_string(),
|
||||
status: Some(status),
|
||||
requested_partitions: vec![],
|
||||
message,
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
@ -86,10 +90,11 @@ pub fn create_analysis_completed_event(
|
|||
create_build_event(
|
||||
build_request_id,
|
||||
build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestAnalysisCompleted as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestAnalysisCompleted.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestAnalysisCompleted.status()),
|
||||
requested_partitions,
|
||||
message: format!("Analysis completed successfully, {} tasks planned", task_count),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
@ -101,7 +106,7 @@ pub fn create_job_scheduled_event(
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::JobEvent(job_event.clone())),
|
||||
}
|
||||
}
|
||||
|
|
@ -113,7 +118,7 @@ pub fn create_job_completed_event(
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::JobEvent(job_event.clone())),
|
||||
}
|
||||
}
|
||||
|
|
@ -125,7 +130,7 @@ pub fn create_partition_available_event(
|
|||
BuildEvent {
|
||||
event_id: generate_event_id(),
|
||||
timestamp: current_timestamp_nanos(),
|
||||
build_request_id,
|
||||
build_request_id: Some(build_request_id),
|
||||
event_type: Some(build_event::EventType::PartitionEvent(partition_event.clone())),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ impl BuildOrchestrator {
|
|||
|
||||
self.event_writer.update_build_status(
|
||||
self.build_request_id.clone(),
|
||||
BuildRequestStatus::BuildRequestPlanning,
|
||||
BuildRequestStatusCode::BuildRequestPlanning.status(),
|
||||
"Starting build planning".to_string(),
|
||||
).await
|
||||
.map_err(OrchestrationError::EventLog)?;
|
||||
|
|
@ -80,7 +80,7 @@ impl BuildOrchestrator {
|
|||
|
||||
self.event_writer.update_build_status(
|
||||
self.build_request_id.clone(),
|
||||
BuildRequestStatus::BuildRequestExecuting,
|
||||
BuildRequestStatusCode::BuildRequestExecuting.status(),
|
||||
"Starting build execution".to_string(),
|
||||
).await
|
||||
.map_err(OrchestrationError::EventLog)?;
|
||||
|
|
@ -95,22 +95,22 @@ impl BuildOrchestrator {
|
|||
|
||||
let (status, message) = match &result {
|
||||
BuildResult::Success { jobs_completed } => {
|
||||
(BuildRequestStatus::BuildRequestCompleted,
|
||||
(BuildRequestStatusCode::BuildRequestCompleted,
|
||||
format!("Build completed successfully with {} jobs", jobs_completed))
|
||||
}
|
||||
BuildResult::Failed { jobs_completed, jobs_failed } => {
|
||||
(BuildRequestStatus::BuildRequestFailed,
|
||||
(BuildRequestStatusCode::BuildRequestFailed,
|
||||
format!("Build failed: {} jobs completed, {} jobs failed", jobs_completed, jobs_failed))
|
||||
}
|
||||
BuildResult::FailFast { trigger_job } => {
|
||||
(BuildRequestStatus::BuildRequestFailed,
|
||||
(BuildRequestStatusCode::BuildRequestFailed,
|
||||
format!("Build failed fast due to job: {}", trigger_job))
|
||||
}
|
||||
};
|
||||
|
||||
self.event_writer.update_build_status(
|
||||
self.build_request_id.clone(),
|
||||
status,
|
||||
status.status(),
|
||||
message,
|
||||
).await
|
||||
.map_err(OrchestrationError::EventLog)?;
|
||||
|
|
@ -122,7 +122,7 @@ impl BuildOrchestrator {
|
|||
pub async fn emit_analysis_completed(&self, task_count: usize) -> Result<()> {
|
||||
self.event_writer.update_build_status_with_partitions(
|
||||
self.build_request_id.clone(),
|
||||
BuildRequestStatus::BuildRequestAnalysisCompleted,
|
||||
BuildRequestStatusCode::BuildRequestAnalysisCompleted.status(),
|
||||
self.requested_partitions.clone(),
|
||||
format!("Analysis completed successfully, {} tasks planned", task_count),
|
||||
).await
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ impl BuildsRepository {
|
|||
let builds = response.builds.into_iter().map(|build| {
|
||||
BuildInfo {
|
||||
build_request_id: build.build_request_id,
|
||||
status: BuildRequestStatus::try_from(build.status_code).unwrap_or(BuildRequestStatus::BuildRequestUnknown),
|
||||
status: build.status.clone().unwrap_or(BuildRequestStatusCode::BuildRequestUnknown.status()),
|
||||
requested_partitions: build.requested_partitions,
|
||||
requested_at: build.requested_at,
|
||||
started_at: build.started_at,
|
||||
|
|
@ -116,7 +116,7 @@ impl BuildsRepository {
|
|||
let mut timeline = Vec::new();
|
||||
for event in all_events {
|
||||
if let Some(crate::build_event::EventType::BuildRequestEvent(br_event)) = &event.event_type {
|
||||
if let Ok(status) = BuildRequestStatus::try_from(br_event.status_code) {
|
||||
if let Some(status) = br_event.clone().status {
|
||||
timeline.push(BuildEvent {
|
||||
timestamp: event.timestamp,
|
||||
event_type: "build_status".to_string(),
|
||||
|
|
@ -151,8 +151,7 @@ impl BuildsRepository {
|
|||
.into_iter()
|
||||
.map(|event| ServiceBuildTimelineEvent {
|
||||
timestamp: event.timestamp,
|
||||
status_code: event.status.map(|s| s as i32),
|
||||
status_name: event.status.map(|s| s.to_display_string()),
|
||||
status: event.status,
|
||||
message: event.message,
|
||||
event_type: event.event_type,
|
||||
cancel_reason: event.cancel_reason,
|
||||
|
|
@ -161,8 +160,7 @@ impl BuildsRepository {
|
|||
|
||||
let response = BuildDetailResponse {
|
||||
build_request_id: build_info.build_request_id,
|
||||
status_code: build_info.status as i32,
|
||||
status_name: build_info.status.to_display_string(),
|
||||
status: Some(build_info.status),
|
||||
requested_partitions: build_info.requested_partitions,
|
||||
total_jobs: build_info.total_jobs as u32,
|
||||
completed_jobs: build_info.completed_jobs as u32,
|
||||
|
|
@ -200,18 +198,18 @@ impl BuildsRepository {
|
|||
let (build, _timeline) = build_info.unwrap();
|
||||
|
||||
// Check if build is in a cancellable state
|
||||
match build.status {
|
||||
BuildRequestStatus::BuildRequestCompleted => {
|
||||
match BuildRequestStatusCode::try_from(build.status.code) {
|
||||
Ok(BuildRequestStatusCode::BuildRequestCompleted) => {
|
||||
return Err(BuildEventLogError::QueryError(
|
||||
format!("Cannot cancel completed build: {}", build_request_id)
|
||||
));
|
||||
}
|
||||
BuildRequestStatus::BuildRequestFailed => {
|
||||
Ok(BuildRequestStatusCode::BuildRequestFailed) => {
|
||||
return Err(BuildEventLogError::QueryError(
|
||||
format!("Cannot cancel failed build: {}", build_request_id)
|
||||
));
|
||||
}
|
||||
BuildRequestStatus::BuildRequestCancelled => {
|
||||
Ok(BuildRequestStatusCode::BuildRequestCancelled) => {
|
||||
return Err(BuildEventLogError::QueryError(
|
||||
format!("Build already cancelled: {}", build_request_id)
|
||||
));
|
||||
|
|
@ -225,10 +223,11 @@ impl BuildsRepository {
|
|||
let cancel_event = create_build_event(
|
||||
build_request_id.to_string(),
|
||||
crate::build_event::EventType::BuildRequestEvent(crate::BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestCancelled as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestCancelled.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestCancelled.status()),
|
||||
requested_partitions: build.requested_partitions,
|
||||
message: format!("Build cancelled"),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -250,8 +249,7 @@ impl BuildsRepository {
|
|||
.into_iter()
|
||||
.map(|build| crate::BuildSummary {
|
||||
build_request_id: build.build_request_id,
|
||||
status_code: build.status as i32,
|
||||
status_name: build.status.to_display_string(),
|
||||
status: Some(build.status),
|
||||
requested_partitions: build.requested_partitions.into_iter().map(|p| crate::PartitionRef { str: p.str }).collect(),
|
||||
total_jobs: build.total_jobs as u32,
|
||||
completed_jobs: build.completed_jobs as u32,
|
||||
|
|
@ -262,6 +260,7 @@ impl BuildsRepository {
|
|||
completed_at: build.completed_at,
|
||||
duration_ms: build.duration_ms,
|
||||
cancelled: build.cancelled,
|
||||
comment: None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -292,10 +291,10 @@ mod tests {
|
|||
|
||||
// Create events for multiple builds
|
||||
let events = vec![
|
||||
test_events::build_request_event(Some(build_id1.clone()), vec![partition1.clone()], BuildRequestStatus::BuildRequestReceived),
|
||||
test_events::build_request_event(Some(build_id1.clone()), vec![partition1.clone()], BuildRequestStatus::BuildRequestCompleted),
|
||||
test_events::build_request_event(Some(build_id2.clone()), vec![partition2.clone()], BuildRequestStatus::BuildRequestReceived),
|
||||
test_events::build_request_event(Some(build_id2.clone()), vec![partition2.clone()], BuildRequestStatus::BuildRequestFailed),
|
||||
test_events::build_request_event(Some(build_id1.clone()), vec![partition1.clone()], BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
test_events::build_request_event(Some(build_id1.clone()), vec![partition1.clone()], BuildRequestStatusCode::BuildRequestCompleted.status()),
|
||||
test_events::build_request_event(Some(build_id2.clone()), vec![partition2.clone()], BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
test_events::build_request_event(Some(build_id2.clone()), vec![partition2.clone()], BuildRequestStatusCode::BuildRequestFailed.status()),
|
||||
];
|
||||
|
||||
let query_engine = create_mock_bel_query_engine_with_events(events).await.unwrap();
|
||||
|
|
@ -308,11 +307,11 @@ mod tests {
|
|||
let build1 = builds.iter().find(|b| b.build_request_id == build_id1).unwrap();
|
||||
let build2 = builds.iter().find(|b| b.build_request_id == build_id2).unwrap();
|
||||
|
||||
assert_eq!(build1.status, BuildRequestStatus::BuildRequestCompleted);
|
||||
assert_eq!(build1.status, BuildRequestStatusCode::BuildRequestCompleted.status());
|
||||
assert_eq!(build1.requested_partitions.len(), 1);
|
||||
assert!(!build1.cancelled);
|
||||
|
||||
assert_eq!(build2.status, BuildRequestStatus::BuildRequestFailed);
|
||||
assert_eq!(build2.status, BuildRequestStatusCode::BuildRequestFailed.status());
|
||||
assert_eq!(build2.requested_partitions.len(), 1);
|
||||
assert!(!build2.cancelled);
|
||||
}
|
||||
|
|
@ -323,10 +322,10 @@ mod tests {
|
|||
let partition = PartitionRef { str: "analytics/daily".to_string() };
|
||||
|
||||
let events = vec![
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestReceived),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestPlanning),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestExecuting),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestCompleted),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestPlanning.status()),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestExecuting.status()),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestCompleted.status()),
|
||||
];
|
||||
|
||||
let query_engine = create_mock_bel_query_engine_with_events(events).await.unwrap();
|
||||
|
|
@ -337,14 +336,14 @@ mod tests {
|
|||
|
||||
let (info, timeline) = result.unwrap();
|
||||
assert_eq!(info.build_request_id, build_id);
|
||||
assert_eq!(info.status, BuildRequestStatus::BuildRequestCompleted);
|
||||
assert_eq!(info.status, BuildRequestStatusCode::BuildRequestCompleted.status());
|
||||
assert!(!info.cancelled);
|
||||
|
||||
assert_eq!(timeline.len(), 4);
|
||||
assert_eq!(timeline[0].status, Some(BuildRequestStatus::BuildRequestReceived));
|
||||
assert_eq!(timeline[1].status, Some(BuildRequestStatus::BuildRequestPlanning));
|
||||
assert_eq!(timeline[2].status, Some(BuildRequestStatus::BuildRequestExecuting));
|
||||
assert_eq!(timeline[3].status, Some(BuildRequestStatus::BuildRequestCompleted));
|
||||
assert_eq!(timeline[0].status, Some(BuildRequestStatusCode::BuildRequestReceived.status()));
|
||||
assert_eq!(timeline[1].status, Some(BuildRequestStatusCode::BuildRequestPlanning.status()));
|
||||
assert_eq!(timeline[2].status, Some(BuildRequestStatusCode::BuildRequestExecuting.status()));
|
||||
assert_eq!(timeline[3].status, Some(BuildRequestStatusCode::BuildRequestCompleted.status()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -363,8 +362,8 @@ mod tests {
|
|||
|
||||
// Start with a running build
|
||||
let events = vec![
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestReceived),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestExecuting),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestExecuting.status()),
|
||||
];
|
||||
|
||||
let query_engine = create_mock_bel_query_engine_with_events(events).await.unwrap();
|
||||
|
|
@ -389,8 +388,8 @@ mod tests {
|
|||
|
||||
// Create a completed build
|
||||
let events = vec![
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestReceived),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatus::BuildRequestCompleted),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestReceived.status()),
|
||||
test_events::build_request_event(Some(build_id.clone()), vec![partition.clone()], BuildRequestStatusCode::BuildRequestCompleted.status()),
|
||||
];
|
||||
|
||||
let query_engine = create_mock_bel_query_engine_with_events(events).await.unwrap();
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl JobsRepository {
|
|||
let job_run = JobRunDetail {
|
||||
job_run_id: j_event.job_run_id.clone(),
|
||||
job_label: job_label.clone(),
|
||||
build_request_id: event.build_request_id.clone(),
|
||||
build_request_id: event.build_request_id.clone().unwrap(),
|
||||
target_partitions: j_event.target_partitions.clone(),
|
||||
status,
|
||||
scheduled_at: event.timestamp,
|
||||
|
|
@ -229,7 +229,7 @@ impl JobsRepository {
|
|||
let job_run = JobRunDetail {
|
||||
job_run_id: j_event.job_run_id.clone(),
|
||||
job_label: job_label.to_string(),
|
||||
build_request_id: event.build_request_id.clone(),
|
||||
build_request_id: event.build_request_id.clone().unwrap(),
|
||||
target_partitions: j_event.target_partitions.clone(),
|
||||
status,
|
||||
scheduled_at: event.timestamp,
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl PartitionsRepository {
|
|||
timestamp: event.timestamp,
|
||||
status: event_status,
|
||||
message: p_event.message.clone(),
|
||||
build_request_id: event.build_request_id,
|
||||
build_request_id: event.build_request_id.unwrap(),
|
||||
job_run_id: if p_event.job_run_id.is_empty() { None } else { Some(p_event.job_run_id.clone()) },
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl TasksRepository {
|
|||
TaskInfo {
|
||||
job_run_id: j_event.job_run_id.clone(),
|
||||
job_label: job_label.clone(),
|
||||
build_request_id: event.build_request_id.clone(),
|
||||
build_request_id: event.build_request_id.clone().unwrap(),
|
||||
status: JobStatus::JobUnknown,
|
||||
target_partitions: j_event.target_partitions.clone(),
|
||||
scheduled_at: event.timestamp,
|
||||
|
|
@ -182,7 +182,7 @@ impl TasksRepository {
|
|||
task_info = Some(TaskInfo {
|
||||
job_run_id: j_event.job_run_id.clone(),
|
||||
job_label: job_label.clone(),
|
||||
build_request_id: event.build_request_id.clone(),
|
||||
build_request_id: event.build_request_id.clone().unwrap(),
|
||||
status: JobStatus::JobUnknown,
|
||||
target_partitions: j_event.target_partitions.clone(),
|
||||
scheduled_at: event.timestamp,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ pub async fn submit_build_request(
|
|||
// Create build request state
|
||||
let build_state = BuildRequestState {
|
||||
build_request_id: build_request_id.clone(),
|
||||
status: BuildRequestStatus::BuildRequestReceived,
|
||||
status: BuildRequestStatusCode::BuildRequestReceived.status(),
|
||||
requested_partitions: request.partitions.clone(),
|
||||
created_at: timestamp,
|
||||
updated_at: timestamp,
|
||||
|
|
@ -160,7 +160,7 @@ pub async fn cancel_build_request(
|
|||
{
|
||||
let mut active_builds = service.active_builds.write().await;
|
||||
if let Some(build_state) = active_builds.get_mut(&build_request_id) {
|
||||
build_state.status = BuildRequestStatus::BuildRequestCancelled;
|
||||
build_state.status = BuildRequestStatusCode::BuildRequestCancelled.status();
|
||||
build_state.updated_at = current_timestamp_nanos();
|
||||
} else {
|
||||
return Err((
|
||||
|
|
@ -176,10 +176,11 @@ pub async fn cancel_build_request(
|
|||
let event = create_build_event(
|
||||
build_request_id.clone(),
|
||||
crate::build_event::EventType::BuildRequestEvent(BuildRequestEvent {
|
||||
status_code: BuildRequestStatus::BuildRequestCancelled as i32,
|
||||
status_name: BuildRequestStatus::BuildRequestCancelled.to_display_string(),
|
||||
status: Some(BuildRequestStatusCode::BuildRequestCancelled.status()),
|
||||
requested_partitions: vec![],
|
||||
message: "Build request cancelled".to_string(),
|
||||
comment: None,
|
||||
want_id: None,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -262,14 +263,14 @@ pub async fn get_partition_events(
|
|||
let decoded_partition_ref = base64_url_decode(&partition_ref).unwrap();
|
||||
|
||||
let events = match service.query_engine.get_partition_events(&decoded_partition_ref, None).await {
|
||||
Ok(events) => events.into_iter().map(|e| {
|
||||
Ok(events) => events.into_iter().filter(|e| e.build_request_id.is_some()).map(|e| {
|
||||
let (job_label, partition_ref, delegated_build_id) = extract_navigation_data(&e.event_type);
|
||||
BuildEventSummary {
|
||||
event_id: e.event_id,
|
||||
timestamp: e.timestamp,
|
||||
event_type: event_type_to_string(&e.event_type),
|
||||
message: event_to_message(&e.event_type),
|
||||
build_request_id: e.build_request_id,
|
||||
build_request_id: e.build_request_id.clone().unwrap(),
|
||||
job_label,
|
||||
partition_ref,
|
||||
delegated_build_id,
|
||||
|
|
@ -350,7 +351,7 @@ async fn execute_build_request(
|
|||
);
|
||||
|
||||
// Update status to planning
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatus::BuildRequestPlanning).await;
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatusCode::BuildRequestPlanning.status()).await;
|
||||
|
||||
// Log planning event
|
||||
if let Err(e) = orchestrator.start_planning().await {
|
||||
|
|
@ -362,7 +363,7 @@ async fn execute_build_request(
|
|||
Ok(graph) => graph,
|
||||
Err(e) => {
|
||||
error!("Failed to analyze build graph: {}", e);
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatus::BuildRequestFailed).await;
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatusCode::BuildRequestFailed.status()).await;
|
||||
|
||||
// Log failure event
|
||||
if let Err(log_err) = orchestrator.complete_build(BuildResult::Failed { jobs_completed: 0, jobs_failed: 1 }).await {
|
||||
|
|
@ -375,7 +376,7 @@ async fn execute_build_request(
|
|||
|
||||
|
||||
// Update status to executing
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatus::BuildRequestExecuting).await;
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatusCode::BuildRequestExecuting.status()).await;
|
||||
|
||||
// Log executing event
|
||||
if let Err(e) = orchestrator.start_execution().await {
|
||||
|
|
@ -386,7 +387,7 @@ async fn execute_build_request(
|
|||
match run_execute_command(&service, &build_request_id, &job_graph).await {
|
||||
Ok(_) => {
|
||||
info!("Build request {} completed successfully", build_request_id);
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatus::BuildRequestCompleted).await;
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatusCode::BuildRequestCompleted.status()).await;
|
||||
|
||||
// Log completion event
|
||||
if let Err(e) = orchestrator.complete_build(BuildResult::Success { jobs_completed: 0 }).await {
|
||||
|
|
@ -397,7 +398,7 @@ async fn execute_build_request(
|
|||
}
|
||||
Err(e) => {
|
||||
error!("Build request {} failed: {}", build_request_id, e);
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatus::BuildRequestFailed).await;
|
||||
update_build_request_status(&service, &build_request_id, BuildRequestStatusCode::BuildRequestFailed.status()).await;
|
||||
|
||||
// Log failure event
|
||||
if let Err(log_err) = orchestrator.complete_build(BuildResult::Failed { jobs_completed: 0, jobs_failed: 1 }).await {
|
||||
|
|
@ -505,7 +506,9 @@ fn event_type_to_string(event_type: &Option<crate::build_event::EventType>) -> S
|
|||
Some(crate::build_event::EventType::PartitionInvalidationEvent(_)) => "partition_invalidation".to_string(),
|
||||
Some(crate::build_event::EventType::JobRunCancelEvent(_)) => "task_cancel".to_string(),
|
||||
Some(crate::build_event::EventType::BuildCancelEvent(_)) => "build_cancel".to_string(),
|
||||
None => "INVALID_EVENT_TYPE".to_string(), // Make this obvious rather than hiding it
|
||||
Some(build_event::EventType::WantEvent(_)) => "want".to_string(),
|
||||
Some(build_event::EventType::TaintEvent(_)) => "taint".to_string(),
|
||||
None => "INVALID_EVENT_TYPE".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -519,7 +522,10 @@ fn event_to_message(event_type: &Option<crate::build_event::EventType>) -> Strin
|
|||
Some(crate::build_event::EventType::PartitionInvalidationEvent(event)) => event.reason.clone(),
|
||||
Some(crate::build_event::EventType::JobRunCancelEvent(event)) => event.reason.clone(),
|
||||
Some(crate::build_event::EventType::BuildCancelEvent(event)) => event.reason.clone(),
|
||||
None => "INVALID_EVENT_NO_MESSAGE".to_string(), // Make this obvious
|
||||
Some(build_event::EventType::WantEvent(event)) => event.comment.clone(),
|
||||
Some(build_event::EventType::TaintEvent(event)) => event.comment.clone(),
|
||||
|
||||
None => "INVALID_EVENT_NO_MESSAGE".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -557,6 +563,12 @@ fn extract_navigation_data(event_type: &Option<crate::build_event::EventType>) -
|
|||
// Build cancel events don't need navigation links
|
||||
(None, None, None)
|
||||
},
|
||||
Some(crate::build_event::EventType::WantEvent(_)) => {
|
||||
(None, None, None)
|
||||
},
|
||||
Some(crate::build_event::EventType::TaintEvent(_)) => {
|
||||
(None, None, None)
|
||||
},
|
||||
None => (None, None, None),
|
||||
}
|
||||
}
|
||||
|
|
@ -1417,8 +1429,7 @@ pub async fn get_build_detail(
|
|||
let timeline_events: Vec<BuildTimelineEvent> = protobuf_response.timeline.into_iter().map(|event| {
|
||||
BuildTimelineEvent {
|
||||
timestamp: event.timestamp,
|
||||
status_code: event.status_code,
|
||||
status_name: event.status_name,
|
||||
status: event.status,
|
||||
message: event.message,
|
||||
event_type: event.event_type,
|
||||
cancel_reason: event.cancel_reason,
|
||||
|
|
@ -1427,8 +1438,7 @@ pub async fn get_build_detail(
|
|||
|
||||
Ok(Json(BuildDetailResponse {
|
||||
build_request_id: protobuf_response.build_request_id,
|
||||
status_code: protobuf_response.status_code,
|
||||
status_name: protobuf_response.status_name,
|
||||
status: protobuf_response.status,
|
||||
requested_partitions: protobuf_response.requested_partitions,
|
||||
total_jobs: protobuf_response.total_jobs,
|
||||
completed_jobs: protobuf_response.completed_jobs,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use serde::{Deserialize, Serialize};
|
|||
use schemars::JsonSchema;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use rusqlite::ToSql;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
@ -398,15 +399,17 @@ impl BuildGraphService {
|
|||
}
|
||||
|
||||
pub fn status_to_string(status: BuildRequestStatus) -> String {
|
||||
match status {
|
||||
BuildRequestStatus::BuildRequestUnknown => "unknown".to_string(),
|
||||
BuildRequestStatus::BuildRequestReceived => "received".to_string(),
|
||||
BuildRequestStatus::BuildRequestPlanning => "planning".to_string(),
|
||||
BuildRequestStatus::BuildRequestAnalysisCompleted => "analysis_completed".to_string(),
|
||||
BuildRequestStatus::BuildRequestExecuting => "executing".to_string(),
|
||||
BuildRequestStatus::BuildRequestCompleted => "completed".to_string(),
|
||||
BuildRequestStatus::BuildRequestFailed => "failed".to_string(),
|
||||
BuildRequestStatus::BuildRequestCancelled => "cancelled".to_string(),
|
||||
match BuildRequestStatusCode::try_from(status.code) {
|
||||
Ok(BuildRequestStatusCode::BuildRequestUnknown) => "unknown".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestReceived) => "received".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestPlanning) => "planning".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestAnalysisCompleted) => "analysis_completed".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestExecuting) => "executing".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestCompleted) => "completed".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestFailed) => "failed".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestCancelled) => "cancelled".to_string(),
|
||||
Ok(BuildRequestStatusCode::BuildRequestPreconditionFailed) => "precondition_failed".to_string(),
|
||||
Err(_) => "error".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,35 +61,44 @@ impl JobStatus {
|
|||
}
|
||||
}
|
||||
|
||||
impl BuildRequestStatus {
|
||||
impl BuildRequestStatusCode {
|
||||
/// Convert build request status to human-readable string matching current CLI/service format
|
||||
pub fn to_display_string(&self) -> String {
|
||||
match self {
|
||||
BuildRequestStatus::BuildRequestUnknown => "unknown".to_string(),
|
||||
BuildRequestStatus::BuildRequestReceived => "received".to_string(),
|
||||
BuildRequestStatus::BuildRequestPlanning => "planning".to_string(),
|
||||
BuildRequestStatus::BuildRequestAnalysisCompleted => "analysis_completed".to_string(),
|
||||
BuildRequestStatus::BuildRequestExecuting => "executing".to_string(),
|
||||
BuildRequestStatus::BuildRequestCompleted => "completed".to_string(),
|
||||
BuildRequestStatus::BuildRequestFailed => "failed".to_string(),
|
||||
BuildRequestStatus::BuildRequestCancelled => "cancelled".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestUnknown => "unknown".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestReceived => "received".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestPlanning => "planning".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestAnalysisCompleted => "analysis_completed".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestExecuting => "executing".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestCompleted => "completed".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestFailed => "failed".to_string(),
|
||||
BuildRequestStatusCode::BuildRequestCancelled => "cancelled".to_string(),
|
||||
&BuildRequestStatusCode::BuildRequestPreconditionFailed => "precondition failed".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a display string back to enum
|
||||
pub fn from_display_string(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"unknown" => Some(BuildRequestStatus::BuildRequestUnknown),
|
||||
"received" => Some(BuildRequestStatus::BuildRequestReceived),
|
||||
"planning" => Some(BuildRequestStatus::BuildRequestPlanning),
|
||||
"analysis_completed" => Some(BuildRequestStatus::BuildRequestAnalysisCompleted),
|
||||
"executing" => Some(BuildRequestStatus::BuildRequestExecuting),
|
||||
"completed" => Some(BuildRequestStatus::BuildRequestCompleted),
|
||||
"failed" => Some(BuildRequestStatus::BuildRequestFailed),
|
||||
"cancelled" => Some(BuildRequestStatus::BuildRequestCancelled),
|
||||
"unknown" => Some(BuildRequestStatusCode::BuildRequestUnknown),
|
||||
"received" => Some(BuildRequestStatusCode::BuildRequestReceived),
|
||||
"planning" => Some(BuildRequestStatusCode::BuildRequestPlanning),
|
||||
"analysis_completed" => Some(BuildRequestStatusCode::BuildRequestAnalysisCompleted),
|
||||
"executing" => Some(BuildRequestStatusCode::BuildRequestExecuting),
|
||||
"completed" => Some(BuildRequestStatusCode::BuildRequestCompleted),
|
||||
"failed" => Some(BuildRequestStatusCode::BuildRequestFailed),
|
||||
"cancelled" => Some(BuildRequestStatusCode::BuildRequestCancelled),
|
||||
"precondition failed" => Some(BuildRequestStatusCode::BuildRequestPreconditionFailed),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn status(&self) -> BuildRequestStatus {
|
||||
BuildRequestStatus {
|
||||
code: self.clone().into(),
|
||||
name: self.to_display_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DepType {
|
||||
|
|
@ -205,11 +214,11 @@ pub mod list_response_helpers {
|
|||
completed_at: Option<i64>,
|
||||
duration_ms: Option<i64>,
|
||||
cancelled: bool,
|
||||
comment: Option<String>,
|
||||
) -> BuildSummary {
|
||||
BuildSummary {
|
||||
build_request_id,
|
||||
status_code: status as i32,
|
||||
status_name: status.to_display_string(),
|
||||
status: Some(status),
|
||||
requested_partitions,
|
||||
total_jobs: total_jobs as u32,
|
||||
completed_jobs: completed_jobs as u32,
|
||||
|
|
@ -220,6 +229,7 @@ pub mod list_response_helpers {
|
|||
completed_at,
|
||||
duration_ms,
|
||||
cancelled,
|
||||
comment,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -256,9 +266,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_build_request_status_conversions() {
|
||||
let status = BuildRequestStatus::BuildRequestCompleted;
|
||||
assert_eq!(status.to_display_string(), "completed");
|
||||
assert_eq!(BuildRequestStatus::from_display_string("completed"), Some(status));
|
||||
let status = BuildRequestStatusCode::BuildRequestCompleted.status();
|
||||
assert_eq!(status.name, "completed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -276,7 +285,7 @@ mod tests {
|
|||
fn test_invalid_display_string() {
|
||||
assert_eq!(PartitionStatus::from_display_string("invalid"), None);
|
||||
assert_eq!(JobStatus::from_display_string("invalid"), None);
|
||||
assert_eq!(BuildRequestStatus::from_display_string("invalid"), None);
|
||||
assert_eq!(BuildRequestStatusCode::from_display_string("invalid"), None);
|
||||
assert_eq!(DepType::from_display_string("invalid"), None);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue