Skip to content

Commit f6e83b4

Browse files
committed
Improve error handling and disable Save until Firestore is ready
1 parent e3409e1 commit f6e83b4

3 files changed

Lines changed: 15 additions & 6 deletions

File tree

src/app/app.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ <h1 class="text-2xl md:text-3xl">
128128
<div class="flex flex-row gap-4 w-full justify-end">
129129
<button
130130
mat-button
131-
[disabled]="!generatedTask"
131+
[disabled]="!generatedTask || !(firestoreReady | async)"
132132
class="w-36 text-md with-bg"
133133
(click)="onSave()"
134134
>

src/app/app.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export class AppComponent {
8787
isLoading = signal(false);
8888
tasks: TaskWithSubtasks[] = [];
8989
generatedTask?: TaskWithSubtasks;
90+
firestoreReady: Observable<boolean>;
9091

9192
@ViewChild('location') locationImage! : CheckboximageComponent;
9293
@ViewChild('room') roomImage! : CheckboximageComponent;
@@ -97,7 +98,9 @@ export class AppComponent {
9798
constructor(
9899
public taskService: TaskService,
99100
private cdr: ChangeDetectorRef,
100-
) {}
101+
) {
102+
this.firestoreReady = this.taskService.firestoreReady;
103+
}
101104

102105
ngOnInit(): void {
103106
this.loadTasks().subscribe();

src/app/services/task.service.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { getApp } from '@angular/fire/app';
2626
import { MatSnackBar } from '@angular/material/snack-bar';
2727
import { retryBackoff } from 'backoff-rxjs';
2828
import { switchMap, tap, take, catchError } from 'rxjs/operators';
29-
import { Observable, of, defer, Subject } from 'rxjs';
29+
import { Observable, of, defer, Subject, BehaviorSubject } from 'rxjs';
3030
import {
3131
doc,
3232
Firestore,
@@ -96,6 +96,10 @@ export class TaskService {
9696

9797
private genAI = new GoogleGenerativeAI(environment.geminiApiKey);
9898
private experimentModel = this.genAI.getGenerativeModel(MODEL_CONFIG);
99+
private firestoreReadySubject = new BehaviorSubject(false);
100+
get firestoreReady(): Observable<boolean> {
101+
return this.firestoreReadySubject.asObservable();
102+
}
99103

100104
user$ = authState(this.auth);
101105
public tasksSubject = new Subject<Task[]>();
@@ -139,17 +143,18 @@ export class TaskService {
139143
}
140144

141145
handleError(error: any, userMessage?: string, duration: number = 3000): void {
146+
const projectId = environment.firebase?.projectId || '';
142147
if (error instanceof GoogleGenerativeAIFetchError) {
143148
if (error.message.indexOf('API key not valid') > 0) {
144-
userMessage = 'Error loading Gemini API key. Please rerun Terraform with `terraform apply --auto-approve`';
149+
userMessage = `Error loading Gemini API key. Please check GCP Console if API key was created at https://console.cloud.google.com/apis/credentials?project=${projectId}`;
145150
} else {
146151
userMessage = error.message;
147152
}
148153
duration = 10000;
149154
}
150155
if (error.message.indexOf('Missing or insufficient permissions') >= 0) {
151156
userMessage =
152-
'Error communicating with Firestore. Please rerun Terraform with `terraform apply --auto-approve`';
157+
`Error communicating with Firestore. Please check status at https://console.firebase.google.com/project/${projectId}/firestore`;
153158
duration = 10000;
154159
}
155160
if (error.message.indexOf('The query requires an index') >= 0) {
@@ -181,10 +186,11 @@ export class TaskService {
181186
retryBackoff({
182187
initialInterval: 500,
183188
maxInterval: 2000,
184-
maxRetries: 10,
189+
maxRetries: 20,
185190
}
186191
),
187192
switchMap((taskCount) => {
193+
this.firestoreReadySubject.next(true);
188194
if (taskCount.data().count === 0) {
189195
return of([] as Task[]);
190196
}

0 commit comments

Comments
 (0)