diff --git a/BaseStyle/BaseStyle/Resource/BaseAssets.xcassets/AccentColor.colorset/Contents.json b/BaseStyle/BaseStyle/Resource/BaseAssets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 000000000..eb8789700 --- /dev/null +++ b/BaseStyle/BaseStyle/Resource/BaseAssets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/BaseStyle/BaseStyle/Resource/BaseAssets.xcassets/Colors/AccentColor.colorset/Contents.json b/BaseStyle/BaseStyle/Resource/BaseAssets.xcassets/Colors/AccentColor.colorset/Contents.json deleted file mode 100644 index 666d86dd6..000000000 --- a/BaseStyle/BaseStyle/Resource/BaseAssets.xcassets/Colors/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "colors" : [ - { - "color" : { - "color-space" : "srgb", - "components" : { - "alpha" : "1.000", - "blue" : "0x00", - "green" : "0xEA", - "red" : "0xAE" - } - }, - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Data/Data/Extension/Double+Extension.swift b/Data/Data/Extension/Double+Extension.swift index 1802a05a8..c316b6363 100644 --- a/Data/Data/Extension/Double+Extension.swift +++ b/Data/Data/Extension/Double+Extension.swift @@ -8,15 +8,26 @@ import Foundation public extension Double { - var formattedCurrency: String { + func formattedCurrency(removeMinusSign: Bool = true) -> String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current if let formattedAmount = formatter.string(from: NSNumber(value: self)) { - return formattedAmount.hasPrefix("-") ? String(formattedAmount.dropFirst()) : formattedAmount + if removeMinusSign && formattedAmount.hasPrefix("-") { + return String(formattedAmount.dropFirst()) + } + return formattedAmount } else { return String(format: "%.2f", self.rounded()) // Fallback to a basic decimal format } } + + var formattedCurrency: String { + return formattedCurrency(removeMinusSign: true) + } + + var formattedCurrencyWithSign: String { + return formattedCurrency(removeMinusSign: false) + } } diff --git a/Data/Data/Repository/ExpenseRepository.swift b/Data/Data/Repository/ExpenseRepository.swift index 02874ad45..db873145f 100644 --- a/Data/Data/Repository/ExpenseRepository.swift +++ b/Data/Data/Repository/ExpenseRepository.swift @@ -20,9 +20,11 @@ public class ExpenseRepository: ObservableObject { } public func deleteExpense(group: Groups, expense: Expense) async throws { + guard let userId = preference.user?.id else { return } + var updatedExpense = expense updatedExpense.isActive = false // Make expense inactive - updatedExpense.updatedBy = preference.user?.id ?? "" + updatedExpense.updatedBy = userId try await updateExpense(group: group, expense: updatedExpense, oldExpense: expense, type: .expenseDeleted) } diff --git a/Data/Data/Repository/GroupRepository.swift b/Data/Data/Repository/GroupRepository.swift index c57481b9b..021f2eed1 100644 --- a/Data/Data/Repository/GroupRepository.swift +++ b/Data/Data/Repository/GroupRepository.swift @@ -19,6 +19,7 @@ public class GroupRepository: ObservableObject { @Inject private var activityLogRepository: ActivityLogRepository private var olderGroupName: String = "" + private var groupMembers: [AppUser] = [] public func createGroup(group: Groups, imageData: Data?) async throws -> Groups { let groupId = try await store.createGroup(group: group) @@ -187,15 +188,32 @@ public class GroupRepository: ObservableObject { } public func fetchMemberBy(userId: String) async throws -> AppUser? { - try await userRepository.fetchUserBy(userID: userId) + if let existingMember = groupMembers.first(where: { $0.id == userId }) { + return existingMember // Return the available member from groupMembers + } else { + let member = try await userRepository.fetchUserBy(userID: userId) + if let member { + self.groupMembers.append(member) + } + return member + } } - public func fetchMembersBy(groupId: String) async throws -> [AppUser] { - guard let group = try await fetchGroupBy(id: groupId) else { return [] } + public func fetchMembersBy(memberIds: [String]) async throws -> [AppUser] { var members: [AppUser] = [] - return try await withThrowingTaskGroup(of: AppUser?.self) { groupTask in - for memberId in group.members { + // Filter out memberIds that already exist in groupMembers to minimize API calls + let missingMemberIds = memberIds.filter { memberId in + let cachedMember = self.groupMembers.first { $0.id == memberId } + return cachedMember == nil + } + + if missingMemberIds.isEmpty { + return self.groupMembers.filter { memberIds.contains($0.id) } + } + + try await withThrowingTaskGroup(of: AppUser?.self) { groupTask in + for memberId in missingMemberIds { groupTask.addTask { try await self.fetchMemberBy(userId: memberId) } @@ -204,9 +222,13 @@ public class GroupRepository: ObservableObject { for try await member in groupTask { if let member { members.append(member) + if !groupMembers.contains(where: { $0.id == member.id }) { + self.groupMembers.append(member) + } } } - return members } + + return members } } diff --git a/Podfile.lock b/Podfile.lock index 9b0a5d125..019ffec70 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1151,6 +1151,10 @@ PODS: - AppAuth/Core (1.7.5) - AppAuth/ExternalUserAgent (1.7.5): - AppAuth/Core + - AppCheckCore (11.0.0): + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) - BoringSSL-GRPC (0.0.36): - BoringSSL-GRPC/Implementation (= 0.0.36) - BoringSSL-GRPC/Interface (= 0.0.36) @@ -1229,8 +1233,9 @@ PODS: - GoogleDataTransport (10.1.0): - nanopb (~> 3.30910.0) - PromisesObjC (~> 2.4) - - GoogleSignIn (7.1.0): + - GoogleSignIn (8.0.0): - AppAuth (< 2.0, >= 1.7.3) + - AppCheckCore (~> 11.0) - GTMAppAuth (< 5.0, >= 4.1.1) - GTMSessionFetcher/Core (~> 3.3) - GoogleUtilities/AppDelegateSwizzler (8.0.2): @@ -1380,6 +1385,7 @@ SPEC REPOS: trunk: - abseil - AppAuth + - AppCheckCore - BoringSSL-GRPC - CocoaLumberjack - Firebase @@ -1414,6 +1420,7 @@ SPEC REPOS: SPEC CHECKSUMS: abseil: d121da9ef7e2ff4cab7666e76c5a3e0915ae08c3 AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa + AppCheckCore: e25aaaac234b333320b0bebb8fc21ed3576819ba BoringSSL-GRPC: ca6a8e5d04812fce8ffd6437810c2d46f925eaeb CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0 Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9 @@ -1430,7 +1437,7 @@ SPEC CHECKSUMS: FirebaseSharedSwift: 9d0e7130af2f0cf162ecd136971f9661f2a3f769 FirebaseStorage: f9e2bf027d549db18b6195a37b31c85f56e40200 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 - GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db + GoogleSignIn: ce8c89bb9b37fb624b92e7514cc67335d1e277e4 GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d "gRPC-C++": 049b3605db691c85d65fbde5b0750b5f54ce9b26 gRPC-Core: d1716d28c3f432b4543bce193e3d7178d59341ef diff --git a/Splito.xcodeproj/project.pbxproj b/Splito.xcodeproj/project.pbxproj index 71cf6ca29..aee472d9b 100644 --- a/Splito.xcodeproj/project.pbxproj +++ b/Splito.xcodeproj/project.pbxproj @@ -1466,7 +1466,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.canopas.splito; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "provision-splito-distribution-2024-03-04"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Splito/AppDelegate.swift b/Splito/AppDelegate.swift index e46efa0e2..da822221e 100644 --- a/Splito/AppDelegate.swift +++ b/Splito/AppDelegate.swift @@ -65,9 +65,7 @@ class AppDelegate: NSObject, UIApplicationDelegate, MessagingDelegate, UNUserNot func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { - if FirebaseProvider.auth.canHandleNotification(userInfo) { - completionHandler(.noData) - } + completionHandler(.noData) } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { diff --git a/Splito/Localization/Localizable.xcstrings b/Splito/Localization/Localizable.xcstrings index 3df473ba1..ea53de2dc 100644 --- a/Splito/Localization/Localizable.xcstrings +++ b/Splito/Localization/Localizable.xcstrings @@ -9,6 +9,9 @@ }, " %@ " : { + }, + " ₹ 0.00" : { + }, " and " : { @@ -108,9 +111,6 @@ }, "%lld people" : { - }, - "+%lld" : { - }, "₹ %@ of %@" : { "extractionState" : "manual" @@ -120,9 +120,6 @@ }, "00:%@" : { - }, - "0.00" : { - }, "1.23" : { "extractionState" : "manual" @@ -185,7 +182,7 @@ "Allow" : { "extractionState" : "manual" }, - "Amount of expense" : { + "Amount" : { "extractionState" : "manual" }, "Ana borrows $10 from Bob" : { @@ -206,7 +203,7 @@ "Are you sure you want to delete this expense? This will remove this expense for ALL people involved, not just you." : { "extractionState" : "manual" }, - "Are you sure you want to delete this transaction?" : { + "Are you sure you want to delete this payment?" : { "extractionState" : "manual" }, "Are you sure you want to remove this member from the group?" : { @@ -215,7 +212,7 @@ "Are you sure you want to restore this expense?" : { "extractionState" : "manual" }, - "Are you sure you want to restore this transaction?" : { + "Are you sure you want to restore this payment?" : { "extractionState" : "manual" }, "Are you sure you want to sign out?" : { @@ -278,7 +275,7 @@ "Delete group" : { "extractionState" : "manual" }, - "Delete Transaction" : { + "Delete payment" : { "extractionState" : "manual" }, "Delete your account" : { @@ -287,6 +284,9 @@ "deleted" : { "extractionState" : "manual" }, + "Description" : { + "extractionState" : "manual" + }, "Done" : { "extractionState" : "manual" }, @@ -335,21 +335,18 @@ "equally" : { "extractionState" : "manual" }, + "Equally" : { + "extractionState" : "manual" + }, "Error" : { "extractionState" : "manual" }, "Expense" : { - }, - "Expense date" : { - "extractionState" : "manual" }, "Expense deleted successfully" : { "extractionState" : "manual" }, - "Expense description" : { - "extractionState" : "manual" - }, "First Name" : { "extractionState" : "manual" }, @@ -485,13 +482,13 @@ "No members in your selected group." : { }, - "No results found for \"%@\"!" : { + "No payments yet!" : { }, - "No results were found that match your search criteria." : { + "No results found for \"%@\"!" : { }, - "No transactions yet!" : { + "No results were found that match your search criteria." : { }, "No unsettled bills yet!" : { @@ -527,7 +524,16 @@ "paid" : { "extractionState" : "manual" }, - "Payment made successfully" : { + "Payment deleted successfully." : { + "extractionState" : "manual" + }, + "Payment detail" : { + "extractionState" : "manual" + }, + "Payment made successfully." : { + "extractionState" : "manual" + }, + "Payments" : { "extractionState" : "manual" }, "Payments made" : { @@ -615,13 +621,13 @@ "Restore group" : { "extractionState" : "manual" }, - "Restore this group to access the settings." : { + "Restore payment" : { "extractionState" : "manual" }, - "Restore this group to enable the search functionality." : { + "Restore this group to access the settings." : { "extractionState" : "manual" }, - "Restore transaction" : { + "Restore this group to enable the search functionality." : { "extractionState" : "manual" }, "restored" : { @@ -648,9 +654,6 @@ "Select which people owe an equal share." : { "extractionState" : "manual" }, - "Select which people owe an equal split." : { - "extractionState" : "manual" - }, "Server error" : { "extractionState" : "manual" }, @@ -708,7 +711,7 @@ "Specify exactly how much each person owes." : { "extractionState" : "manual" }, - "Spilt options" : { + "Spilt option" : { "extractionState" : "manual" }, "Split by exact amounts" : { @@ -726,7 +729,7 @@ "Split your expenses between friends and colleagues with ease!" : { "extractionState" : "manual" }, - "Start spending or receiving money to see your transactions here." : { + "Start spending or receiving money to see your payments here." : { }, "Stay In Touch" : { @@ -753,7 +756,7 @@ "The group associated with this expense has been deleted, so it cannot be restored." : { "extractionState" : "manual" }, - "The group associated with this transaction has been deleted, so it cannot be restored." : { + "The group associated with this payment has been deleted, so it cannot be restored." : { "extractionState" : "manual" }, "The payment values do not add up to the total cost of ₹ %@. You are short by ₹ %@." : { @@ -786,6 +789,12 @@ "This month" : { "extractionState" : "manual" }, + "This payment could not be deleted. You do not have permission to delete this payment, Sorry!" : { + "extractionState" : "manual" + }, + "This payment could not be edited. You do not have permission to edit this payment, Sorry!" : { + "extractionState" : "manual" + }, "This payment involves a person who has left the group, and thus it can no longer be deleted. If you wish to change this payment, you must first add that person back to your group." : { "extractionState" : "manual" }, @@ -798,13 +807,7 @@ "This payment was noted using the \"record a payment\" feature, No money has been transferred." : { }, - "This transaction could not be deleted. You do not have permission to delete this transaction, Sorry!" : { - "extractionState" : "manual" - }, - "This transaction could not be edited. You do not have permission to edit this transaction, Sorry!" : { - "extractionState" : "manual" - }, - "This will restore all activities, expenses and transactions for this group." : { + "This will restore all activities, expenses and payments for this group." : { "extractionState" : "manual" }, "This year" : { @@ -834,10 +837,7 @@ "Totals" : { "extractionState" : "manual" }, - "Transaction deleted successfully" : { - "extractionState" : "manual" - }, - "unequally" : { + "Unequally" : { "extractionState" : "manual" }, "Unknown" : { @@ -903,7 +903,7 @@ "you borrowed" : { }, - "You can restore it to recover all activities, expenses and transactions." : { + "You can restore it to recover all activities, expenses and payments." : { "extractionState" : "manual" }, "You can't leave this group because you have outstanding debts with other group members. Please make sure all of your debts have been settle up, and try again." : { @@ -930,7 +930,7 @@ "You must select at least one person to split with." : { }, - "You no longer have access to this group's activities, expenses and transactions." : { + "You no longer have access to this group's activities, expenses and payments." : { "extractionState" : "manual" }, "you owe" : { diff --git a/Splito/Resource/Assets.xcassets/AccentColor.colorset/Contents.json b/Splito/Resource/Assets.xcassets/AccentColor.colorset/Contents.json index 666d86dd6..eb8789700 100644 --- a/Splito/Resource/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/Splito/Resource/Assets.xcassets/AccentColor.colorset/Contents.json @@ -1,15 +1,6 @@ { "colors" : [ { - "color" : { - "color-space" : "srgb", - "components" : { - "alpha" : "1.000", - "blue" : "0x00", - "green" : "0xEA", - "red" : "0xAE" - } - }, "idiom" : "universal" } ], diff --git a/Splito/UI/Home/Account/AccountHomeView.swift b/Splito/UI/Home/Account/AccountHomeView.swift index 195445309..c02fdd29b 100644 --- a/Splito/UI/Home/Account/AccountHomeView.swift +++ b/Splito/UI/Home/Account/AccountHomeView.swift @@ -55,7 +55,7 @@ struct AccountHomeView: View { } } .background(surfaceColor) - .toastView(toast: $viewModel.toast, bottomPadding: 32) + .toastView(toast: $viewModel.toast) .backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert) .sheet(isPresented: $viewModel.showShareSheet) { MailComposeView(logFilePath: viewModel.logFilePath, showToast: viewModel.showMailSendToast) diff --git a/Splito/UI/Home/ActivityLog/ActivityLogView.swift b/Splito/UI/Home/ActivityLog/ActivityLogView.swift index aee96d76c..590f103cb 100644 --- a/Splito/UI/Home/ActivityLog/ActivityLogView.swift +++ b/Splito/UI/Home/ActivityLog/ActivityLogView.swift @@ -70,9 +70,7 @@ private struct ActivityLogListView: View { if viewModel.hasMoreLogs { ProgressView() - .onAppear { - viewModel.loadMoreActivityLogs() - } + .onAppear(perform: viewModel.loadMoreActivityLogs) } } .padding(.bottom, 62) diff --git a/Splito/UI/Home/ActivityLog/ActivityLogViewModel.swift b/Splito/UI/Home/ActivityLog/ActivityLogViewModel.swift index 478e7d9bf..84efe1c71 100644 --- a/Splito/UI/Home/ActivityLog/ActivityLogViewModel.swift +++ b/Splito/UI/Home/ActivityLog/ActivityLogViewModel.swift @@ -55,7 +55,6 @@ class ActivityLogViewModel: BaseViewModel, ObservableObject { } do { - viewState = .loading let result = try await activityLogRepository.fetchActivitiesBy(userId: userId, limit: ACTIVITY_LOG_LIMIT) activityLogs = result.data diff --git a/Splito/UI/Home/Expense/AddExpenseView.swift b/Splito/UI/Home/Expense/AddExpenseView.swift index c8d49761c..e7c47cd7d 100644 --- a/Splito/UI/Home/Expense/AddExpenseView.swift +++ b/Splito/UI/Home/Expense/AddExpenseView.swift @@ -25,33 +25,9 @@ struct AddExpenseView: View { VStack(spacing: 0) { VSpacer(16) - VStack(spacing: 16) { - ExpenseDetailRowWithBtn(name: viewModel.selectedGroup?.name ?? "Select group", - subtitle: "With you and:", onTap: viewModel.handleGroupBtnAction) - - ExpenseDetailRow(name: $viewModel.expenseName, amount: .constant(0), - date: $viewModel.expenseDate, focusedField: $focusedField, - subtitle: "Expense description", placeholder: "Enter a description", - field: .expenseName) - - ExpenseDetailRow(name: .constant(""), amount: $viewModel.expenseAmount, - date: $viewModel.expenseDate, focusedField: $focusedField, - subtitle: "Amount of expense", placeholder: "0.00", - field: .amount, keyboardType: .decimalPad) - - ExpenseDetailRow(name: .constant(""), amount: .constant(0), - date: $viewModel.expenseDate, focusedField: $focusedField, - subtitle: "Date", placeholder: "Expense date") - - ExpenseDetailRowWithBtn(name: viewModel.payerName, subtitle: "Paid by", - onTap: viewModel.handlePayerBtnAction) - - ExpenseDetailRowWithBtn(name: "Select which people owe an equal split.", - subtitle: "Spilt options", - memberProfileUrls: viewModel.memberProfileUrls, - onTap: viewModel.handleSplitTypeBtnAction) - } - .padding(.horizontal, 1) + ExpenseInfoView(viewModel: viewModel, focusedField: $focusedField) + + Spacer(minLength: 40) } } .scrollIndicators(.hidden) @@ -113,30 +89,64 @@ struct AddExpenseView: View { } } } - .onAppear { - focusedField = .expenseName - } .onTapGesture { focusedField = nil } } } +private struct ExpenseInfoView: View { + + @ObservedObject var viewModel: AddExpenseViewModel + + var focusedField: FocusState.Binding + + var body: some View { + VStack(spacing: 16) { + ExpenseDetailRow(name: $viewModel.expenseName, date: $viewModel.expenseDate, focusedField: focusedField, + subtitle: "With you and:", inputValue: viewModel.selectedGroup?.name ?? "Select group", + showButton: true, onTap: viewModel.handleGroupBtnAction) + + ExpenseDetailRow(name: $viewModel.expenseName, date: $viewModel.expenseDate, focusedField: focusedField, + subtitle: "Description", field: .expenseName) + + AmountRowView(amount: $viewModel.expenseAmount, subtitle: "Amount") + .onTapGesture { + focusedField.wrappedValue = .amount + } + .focused(focusedField, equals: .amount) + .padding(.vertical, 8) + + ExpenseDetailRow(name: $viewModel.expenseName, date: $viewModel.expenseDate, + focusedField: focusedField, subtitle: "Date", field: .date) + + HStack(alignment: .top, spacing: 16) { + ExpenseDetailRow(name: $viewModel.expenseName, date: $viewModel.expenseDate, focusedField: focusedField, + subtitle: "Paid by", inputValue: viewModel.payerName, onTap: viewModel.handlePayerBtnAction) + + ExpenseDetailRow(name: $viewModel.expenseName, date: $viewModel.expenseDate, focusedField: focusedField, + subtitle: "Spilt option", inputValue: viewModel.splitType == .equally ? "Equally" : "Unequally", + onTap: viewModel.handleSplitTypeBtnAction) + } + } + .padding(.horizontal, 1) + } +} + private struct ExpenseDetailRow: View { @Binding var name: String - @Binding var amount: Double @Binding var date: Date var focusedField: FocusState.Binding let subtitle: String - let placeholder: String - + var inputValue: String = "" + var showButton: Bool = false var field: AddExpenseViewModel.AddExpenseField? - var keyboardType: UIKeyboardType = .default + + var onTap: (() -> Void)? @State private var showDatePicker = false - @State private var amountString: String = "" var body: some View { VStack(alignment: .leading, spacing: 8) { @@ -145,53 +155,46 @@ private struct ExpenseDetailRow: View { .foregroundStyle(disableText) VStack(alignment: .leading, spacing: 0) { - if field != .amount && field != .expenseName { + if field == .date { DatePickerRow(date: $date) + } else if field == .expenseName { + TextField("Enter a description", text: $name) + .font(.subTitle2()) + .foregroundStyle(primaryText) + .keyboardType(.default) + .onTapGesture { + focusedField.wrappedValue = .expenseName + } + .tint(primaryColor) + .focused(focusedField, equals: field) + .autocorrectionDisabled() + .submitLabel(.next) + .onSubmit { + focusedField.wrappedValue = .amount + } } else { - if keyboardType == .default { - TextField(placeholder.localized, text: $name) + HStack(spacing: 16) { + Text(inputValue.localized) .font(.subTitle2()) .foregroundStyle(primaryText) - .onTapGesture { - focusedField.wrappedValue = .expenseName - } - .tint(primaryColor) - .focused(focusedField, equals: field) - .autocorrectionDisabled() - .submitLabel(.next) - .onSubmit { - focusedField.wrappedValue = .amount - } - } else { - TextField(placeholder.localized, text: $amountString) - .font(.subTitle2()) - .foregroundStyle(primaryText) - .onTapGesture { - focusedField.wrappedValue = .amount - } - .tint(primaryColor) - .focused(focusedField, equals: field) - .autocorrectionDisabled() - .keyboardType(keyboardType) - .onChange(of: amountString) { newValue in - if let value = Double(newValue) { - amount = value - } else { - amount = 0 - } - } - .onAppear { - amountString = amount == 0 ? "" : String(format: "%.2f", amount) - } + + Spacer() + + if showButton { + ScrollToTopButton(icon: "chevron.down", iconColor: disableText, bgColor: surfaceColor, + size: (12, 12), padding: 0, onClick: onTap) + } } } } - .padding(.vertical, 14) - .padding(.horizontal, 16) + .padding(16) .overlay { RoundedRectangle(cornerRadius: 12) .stroke(outlineColor, lineWidth: 1) } + .onTapGestureForced { + onTap?() + } } } } @@ -239,13 +242,12 @@ struct DatePickerRow: View { ) .padding(.leading, 16) - Spacer(minLength: 0) - ScrollView { DatePicker("", selection: $tempDate, in: ...maximumDate, displayedComponents: .date) .datePickerStyle(GraphicalDatePickerStyle()) .labelsHidden() .padding(24) + .id(tempDate) } .scrollIndicators(.hidden) @@ -261,67 +263,3 @@ struct DatePickerRow: View { } } } - -private struct ExpenseDetailRowWithBtn: View { - let IMAGE_HEIGHT: CGFloat = 26 - - let name: String - let subtitle: String - var memberProfileUrls: [String] = [] - - let onTap: () -> Void - - private var visibleProfileUrls: [String] { - Array(memberProfileUrls.prefix(5)) - } - - private var additionalMembersCount: Int { - max(memberProfileUrls.count - 5, 0) - } - - var body: some View { - VStack(alignment: .leading, spacing: 8) { - Text(subtitle.localized) - .font(.body3()) - .foregroundStyle(disableText) - - VStack(alignment: .leading, spacing: 12) { - HStack(spacing: 0) { - Text(name.localized) - .font(.subTitle2()) - .foregroundStyle(primaryText) - - Spacer() - - ScrollToTopButton(icon: "chevron.down", iconColor: disableText, - bgColor: surfaceColor, size: (12, 12), padding: 0, onClick: onTap) - } - - if !memberProfileUrls.isEmpty { - HStack(spacing: -10) { - ForEach(visibleProfileUrls, id: \.self) { imageUrl in - MemberProfileImageView(imageUrl: imageUrl, height: IMAGE_HEIGHT, - scaleEffect: 0.7, defaultImageBgColor: containerColor) - } - - if additionalMembersCount > 0 { - Text("+\(additionalMembersCount)") - .font(.caption1()) - .foregroundStyle(primaryText) - .frame(width: 26, height: 26) - .background(containerColor) - .clipShape(Circle()) - } - } - } - } - .padding(.vertical, 14) - .padding(.horizontal, 16) - .overlay { - RoundedRectangle(cornerRadius: 12) - .stroke(outlineColor, lineWidth: 1) - } - } - .onTapGestureForced(perform: onTap) - } -} diff --git a/Splito/UI/Home/Expense/AddExpenseViewModel.swift b/Splito/UI/Home/Expense/AddExpenseViewModel.swift index fb9d6664e..c72469ce2 100644 --- a/Splito/UI/Home/Expense/AddExpenseViewModel.swift +++ b/Splito/UI/Home/Expense/AddExpenseViewModel.swift @@ -417,5 +417,6 @@ extension AddExpenseViewModel { enum AddExpenseField { case expenseName case amount + case date } } diff --git a/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerView.swift b/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerView.swift index 6fe00b104..c3dcfc668 100644 --- a/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerView.swift +++ b/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerView.swift @@ -28,7 +28,7 @@ struct ChooseMultiplePayerView: View { Spacer(minLength: 0) if .noInternet == viewModel.currentViewState || .somethingWentWrong == viewModel.currentViewState { - ErrorView(isForNoInternet: viewModel.currentViewState == .noInternet, onClick: viewModel.fetchInitialMembersData) + ErrorView(isForNoInternet: viewModel.currentViewState == .noInternet, onClick: viewModel.fetchInitialViewData) } else if case .loading = viewModel.currentViewState { LoaderView() } else { @@ -46,7 +46,7 @@ struct ChooseMultiplePayerView: View { .scrollBounceBehavior(.basedOnSize) BottomInfoCardView(title: "₹ \(String(format: "%.2f", viewModel.totalAmount)) of \(viewModel.expenseAmount.formattedCurrency)", - value: "\((viewModel.expenseAmount - viewModel.totalAmount).formattedCurrency) left") + value: "\((viewModel.expenseAmount - viewModel.totalAmount).formattedCurrencyWithSign) left") } } .background(surfaceColor) diff --git a/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerViewModel.swift b/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerViewModel.swift index 8b00b05d3..d3c6ea4f5 100644 --- a/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerViewModel.swift +++ b/Splito/UI/Home/Expense/Detail Selection/Payer/ChooseMultiplePayerViewModel.swift @@ -41,19 +41,23 @@ class ChooseMultiplePayerViewModel: BaseViewModel, ObservableObject { totalAmount = expenseAmount } - fetchInitialMembersData() + fetchInitialViewData() } - func fetchInitialMembersData() { + func fetchInitialViewData() { Task { - await self.fetchMembers() + await self.fetchGroupWithMembers() } } - private func fetchMembers() async { + private func fetchGroupWithMembers() async { do { - let users = try await groupRepository.fetchMembersBy(groupId: groupId) - groupMembers = users + let group = try await groupRepository.fetchGroupBy(id: groupId) + guard let group else { + currentViewState = .initial + return + } + groupMembers = try await groupRepository.fetchMembersBy(memberIds: group.members) currentViewState = .initial } catch { handleServiceError() diff --git a/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerView.swift b/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerView.swift index b1b8c0d25..b8034902b 100644 --- a/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerView.swift +++ b/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerView.swift @@ -28,7 +28,7 @@ struct ChoosePayerView: View { Spacer(minLength: 0) if .noInternet == viewModel.currentViewState || .somethingWentWrong == viewModel.currentViewState { - ErrorView(isForNoInternet: viewModel.currentViewState == .noInternet, onClick: viewModel.fetchInitialMembersData) + ErrorView(isForNoInternet: viewModel.currentViewState == .noInternet, onClick: viewModel.fetchInitialViewData) } else if case .loading = viewModel.currentViewState { LoaderView() } else if case .noMember = viewModel.currentViewState { diff --git a/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerViewModel.swift b/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerViewModel.swift index 05aa5c06f..6b7f6e531 100644 --- a/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerViewModel.swift +++ b/Splito/UI/Home/Expense/Detail Selection/Payer/ChoosePayerViewModel.swift @@ -29,19 +29,24 @@ class ChoosePayerViewModel: BaseViewModel, ObservableObject { self.onPayerSelection = onPayerSelection super.init() - fetchInitialMembersData() + fetchInitialViewData() } - func fetchInitialMembersData() { + func fetchInitialViewData() { Task { - await self.fetchMembers() + await fetchGroupWithMembers() } } // MARK: - Data Loading - private func fetchMembers() async { + private func fetchGroupWithMembers() async { do { - let users = try await groupRepository.fetchMembersBy(groupId: groupId) + let group = try await groupRepository.fetchGroupBy(id: groupId) + guard let group else { + currentViewState = .noMember + return + } + let users = try await groupRepository.fetchMembersBy(memberIds: group.members) currentViewState = users.isEmpty ? .noMember : .hasMembers(users) } catch { handleServiceError() diff --git a/Splito/UI/Home/Expense/Detail Selection/SelectGroupView.swift b/Splito/UI/Home/Expense/Detail Selection/SelectGroupView.swift index 271d855f7..c5e9d57cb 100644 --- a/Splito/UI/Home/Expense/Detail Selection/SelectGroupView.swift +++ b/Splito/UI/Home/Expense/Detail Selection/SelectGroupView.swift @@ -37,13 +37,17 @@ struct SelectGroupView: View { VStack(alignment: .leading, spacing: 0) { ForEach(groups) { group in - GroupCellView(group: group, isSelected: group.id == viewModel.selectedGroup?.id, action: { - viewModel.handleGroupSelection(group: group) - }) + GroupCellView(group: group, isSelected: group.id == viewModel.selectedGroup?.id, + isLastGroup: groups.last?.id == group.id, + action: { + viewModel.handleGroupSelection(group: group) + }) .onTapGestureForced { viewModel.handleGroupSelection(group: group) } } + + VSpacer(40) } .frame(maxWidth: isIpad ? 600 : nil, alignment: .center) .frame(maxWidth: .infinity, alignment: .center) @@ -94,6 +98,7 @@ private struct GroupCellView: View { var group: Groups var isSelected: Bool + let isLastGroup: Bool var action: () -> Void @@ -112,9 +117,11 @@ private struct GroupCellView: View { .padding(.horizontal, 16) .frame(maxWidth: .infinity, alignment: .leading) - Divider() - .frame(height: 1) - .background(dividerColor) - .padding(.vertical, 20) + if !isLastGroup { + Divider() + .frame(height: 1) + .background(dividerColor) + .padding(.vertical, 20) + } } } diff --git a/Splito/UI/Home/Expense/Expense Split Option/ExpenseSplitOptionsView.swift b/Splito/UI/Home/Expense/Expense Split Option/ExpenseSplitOptionsView.swift index 651b8f83d..ef8ae929b 100644 --- a/Splito/UI/Home/Expense/Expense Split Option/ExpenseSplitOptionsView.swift +++ b/Splito/UI/Home/Expense/Expense Split Option/ExpenseSplitOptionsView.swift @@ -76,7 +76,7 @@ private struct SplitOptionsBottomView: View { isForEqualSplit: true, onAllBtnTap: viewModel.handleAllBtnAction) case .fixedAmount: BottomInfoCardView(title: "₹ \(String(format: "%.2f", viewModel.totalFixedAmount)) of \(viewModel.expenseAmount.formattedCurrency)", - value: "\((viewModel.expenseAmount - viewModel.totalFixedAmount).formattedCurrency) left") + value: "\((viewModel.expenseAmount - viewModel.totalFixedAmount).formattedCurrencyWithSign) left") case .percentage: BottomInfoCardView(title: "\(String(format: "%.0f", viewModel.totalPercentage))% of 100%", value: "\(String(format: "%.0f", 100 - viewModel.totalPercentage))% left") diff --git a/Splito/UI/Home/Groups/Create Group/CreateGroupView.swift b/Splito/UI/Home/Groups/Create Group/CreateGroupView.swift index a8d760475..a239ab37e 100644 --- a/Splito/UI/Home/Groups/Create Group/CreateGroupView.swift +++ b/Splito/UI/Home/Groups/Create Group/CreateGroupView.swift @@ -141,7 +141,7 @@ struct ImagePickerOptionsView: View { handleActionSelection(.gallery) } if image != nil || imageUrl != nil { - Button("Remove") { + Button("Remove", role: .destructive) { handleActionSelection(.remove) } } diff --git a/Splito/UI/Home/Groups/Create Group/CreateGroupViewModel.swift b/Splito/UI/Home/Groups/Create Group/CreateGroupViewModel.swift index 9ed45bb06..68513b7e7 100644 --- a/Splito/UI/Home/Groups/Create Group/CreateGroupViewModel.swift +++ b/Splito/UI/Home/Groups/Create Group/CreateGroupViewModel.swift @@ -116,9 +116,11 @@ class CreateGroupViewModel: BaseViewModel, ObservableObject { } private func updateGroup(group: Groups) async -> Bool { + guard let userId = preference.user?.id else { return false } + var newGroup = group newGroup.name = groupName.trimming(spaces: .leadingAndTrailing) - newGroup.updatedBy = preference.user?.id ?? "" + newGroup.updatedBy = userId newGroup.updatedAt = Timestamp() let resizedImage = profileImage?.aspectFittedToHeight(200) diff --git a/Splito/UI/Home/Groups/Group/Group Options/Balances/GroupBalancesViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Balances/GroupBalancesViewModel.swift index 8635e6080..442828f2f 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Balances/GroupBalancesViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Balances/GroupBalancesViewModel.swift @@ -40,25 +40,21 @@ class GroupBalancesViewModel: BaseViewModel, ObservableObject { func fetchInitialBalancesData() { Task { - await fetchGroupMembers() + await fetchGroupWithMembers() } } // MARK: - Data Loading - func fetchGroupMembers() async { + func fetchGroupWithMembers() async { do { - groupMemberData = try await groupRepository.fetchMembersBy(groupId: groupId) - await fetchGroupDetails() - viewState = .initial - } catch { - handleServiceError() - } - } - - private func fetchGroupDetails() async { - do { - group = try await groupRepository.fetchGroupBy(id: groupId) + self.group = try await groupRepository.fetchGroupBy(id: groupId) + guard let group else { + viewState = .initial + return + } + groupMemberData = try await groupRepository.fetchMembersBy(memberIds: group.members) calculateExpensesSimplified() + viewState = .initial } catch { handleServiceError() } @@ -72,12 +68,14 @@ class GroupBalancesViewModel: BaseViewModel, ObservableObject { return } - let memberBalances = group.balances.map { + let filteredBalances = group.balances.filter { group.members.contains($0.id) } + + let memberBalances = filteredBalances.map { MembersCombinedBalance(id: $0.id, totalOwedAmount: $0.balance) } // Create group member balances for settlements - let groupMemberBalances = group.balances.map { + let groupMemberBalances = filteredBalances.map { GroupMemberBalance(id: $0.id, balance: $0.balance, totalSummary: $0.totalSummary) } @@ -153,7 +151,7 @@ class GroupBalancesViewModel: BaseViewModel, ObservableObject { @objc private func handleAddTransaction(notification: Notification) { showToastFor(toast: .init(type: .success, title: "Success", message: "Payment made successfully.")) Task { - await fetchGroupDetails() + await fetchGroupWithMembers() } } diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/GroupSettleUpViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/GroupSettleUpViewModel.swift index 5fe3a351a..43de71cb6 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/GroupSettleUpViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/GroupSettleUpViewModel.swift @@ -61,14 +61,14 @@ class GroupSettleUpViewModel: BaseViewModel, ObservableObject { } private func fetchGroupMembers() async { + guard let group, let userId = preference.user?.id else { + viewState = .initial + return + } + do { viewState = .loading - guard let userId = preference.user?.id else { - viewState = .initial - return - } - let members = try await groupRepository.fetchMembersBy(groupId: groupId) - self.members = members + self.members = try await groupRepository.fetchMembersBy(memberIds: group.members) self.members.removeAll(where: { $0.id == userId }) viewState = .initial } catch { diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentView.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentView.swift index 869d89fe3..fdd169d33 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentView.swift @@ -24,20 +24,24 @@ struct GroupPaymentView: View { } else { ScrollView { VStack(alignment: .center, spacing: 0) { - VSpacer(27) + VSpacer(16) - VStack(alignment: .center, spacing: 24) { + VStack(alignment: .center, spacing: 16) { HStack(alignment: .center, spacing: 24) { ProfileCardView(name: viewModel.payerName, imageUrl: viewModel.payer?.imageUrl, geometry: geometry) Image(.transactionIcon) .resizable() - .frame(width: 35, height: 36) - .padding(7) + .scaledToFit() + .frame(width: 42, height: 42) ProfileCardView(name: viewModel.payableName, imageUrl: viewModel.receiver?.imageUrl, geometry: geometry) } + Divider() + .frame(height: 1) + .background(outlineColor) + Text("\(viewModel.payerName.localized) paid \(viewModel.payableName.localized)") .font(.body3()) .foregroundStyle(disableText) @@ -45,14 +49,17 @@ struct GroupPaymentView: View { .multilineTextAlignment(.center) } .padding(16) + .frame(maxWidth: .infinity, alignment: .center) + .background(container2Color) + .cornerRadius(16) - VSpacer(40) + VSpacer(16) - PaymentDetailRow(amount: $viewModel.amount, date: $viewModel.paymentDate, subtitle: "Date", placeholder: "Enter payment date", forDatePicker: true) + AmountRowView(amount: $viewModel.amount, subtitle: "Enter amount") VSpacer(16) - PaymentDetailRow(amount: $viewModel.amount, date: $viewModel.paymentDate, subtitle: "Enter amount", placeholder: "0.00") + PaymentDateRow(date: $viewModel.paymentDate, subtitle: "Date") Spacer(minLength: 40) } @@ -92,18 +99,13 @@ struct GroupPaymentView: View { } } -private struct PaymentDetailRow: View { +private struct PaymentDateRow: View { - @Binding var amount: Double @Binding var date: Date let subtitle: String - let placeholder: String - var forDatePicker: Bool = false - @FocusState var isAmountFocused: Bool @State private var showDatePicker: Bool = false - @State private var amountString: String = "" var body: some View { VStack(alignment: .leading, spacing: 8) { @@ -111,38 +113,65 @@ private struct PaymentDetailRow: View { .font(.body3()) .foregroundStyle(disableText) - VStack(alignment: .leading, spacing: 0) { - if forDatePicker { - DatePickerRow(date: $date) - } else { - TextField("0.00", text: $amountString) - .keyboardType(.decimalPad) - .font(.subTitle2()) - .tint(primaryColor) - .foregroundStyle(primaryText) - .focused($isAmountFocused) - .frame(maxWidth: .infinity, alignment: .leading) - .onChange(of: amountString) { newValue in - if let value = Double(newValue) { - amount = value - } else { - amount = 0 - } - } - .onAppear { - amountString = amount == 0 ? "" : String(format: "%.2f", amount) - } + DatePickerRow(date: $date) + .padding(16) + .overlay { + RoundedRectangle(cornerRadius: 12) + .stroke(outlineColor, lineWidth: 1) } - } - .padding(.vertical, 14) - .padding(.horizontal, 16) - .overlay { - RoundedRectangle(cornerRadius: 12) - .stroke(outlineColor, lineWidth: 1) - } - .onAppear { - isAmountFocused = true - } } } } + +struct AmountRowView: View { + + @Binding var amount: Double + + let subtitle: String + + @FocusState var isAmountFocused: Bool + @State private var amountString: String = "" + + var body: some View { + VStack(alignment: .center, spacing: 24) { + Text(subtitle.localized) + .font(.subTitle1()) + .foregroundStyle(primaryText) + .tracking(-0.2) + + TextField(" ₹ 0.00", text: $amountString) + .keyboardType(.decimalPad) + .font(.Header1()) + .tint(primaryColor) + .foregroundStyle(amountString.isEmpty ? outlineColor : primaryText) + .focused($isAmountFocused) + .multilineTextAlignment(.center) + .autocorrectionDisabled() + .onChange(of: amountString) { newValue in + formatAmount(newValue: newValue) + } + .onAppear { + amountString = amount == 0 ? "" : String(format: "₹ %.2f", amount) + isAmountFocused = true + } + } + .padding(16) + .overlay { + RoundedRectangle(cornerRadius: 16) + .stroke(outlineColor, lineWidth: 1) + } + } + + private func formatAmount(newValue: String) { + // Remove the "₹" symbol and whitespace to process the numeric value + let numericInput = newValue.replacingOccurrences(of: "₹", with: "").trimmingCharacters(in: .whitespaces) + if let value = Double(numericInput) { + amount = value + } else { + amount = 0 + } + + // Update amountString to include "₹" prefix + amountString = numericInput.isEmpty ? "" : "₹ " + numericInput + } +} diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift index 1adba1cd0..be433a0af 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift @@ -31,7 +31,7 @@ class GroupPaymentViewModel: BaseViewModel, ObservableObject { var payableName: String { guard let user = preference.user else { return "" } - return user.id == receiverId ? "You" : receiver?.nameWithLastInitial ?? "Unknown" + return user.id == receiverId ? "you" : receiver?.nameWithLastInitial ?? "unknown" } private var group: Groups? @@ -110,6 +110,8 @@ class GroupPaymentViewModel: BaseViewModel, ObservableObject { } func showSaveFailedError() { + guard amount > 0 else { return } + guard validateGroupMembers() else { showAlertFor(message: "This payment involves a person who has left the group, and thus it can no longer be edited. If you wish to change this payment, you must first add that person back to your group.") return diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidView.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidView.swift index dd231c0fb..706df949c 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidView.swift @@ -15,7 +15,7 @@ struct GroupWhoGettingPaidView: View { var body: some View { VStack(alignment: .leading, spacing: 0) { if .noInternet == viewModel.viewState || .somethingWentWrong == viewModel.viewState { - ErrorView(isForNoInternet: viewModel.viewState == .noInternet, onClick: viewModel.fetchInitialMembersData) + ErrorView(isForNoInternet: viewModel.viewState == .noInternet, onClick: viewModel.fetchInitialViewData) } else if case .loading = viewModel.viewState { LoaderView() } else { @@ -41,7 +41,7 @@ struct GroupWhoGettingPaidView: View { .background(surfaceColor) .toastView(toast: $viewModel.toast) .backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert) - .onAppear(perform: viewModel.fetchInitialMembersData) + .onAppear(perform: viewModel.fetchInitialViewData) .toolbarRole(.editor) .toolbar { ToolbarItem(placement: .topBarLeading) { diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidViewModel.swift index 12a0c330a..4d4ece18b 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Getting Paid/GroupWhoGettingPaidViewModel.swift @@ -28,17 +28,21 @@ class GroupWhoGettingPaidViewModel: BaseViewModel, ObservableObject { super.init() } - func fetchInitialMembersData() { + func fetchInitialViewData() { Task { - await fetchGroupMembers() + await fetchGroupWithMembers() } } // MARK: - Data Loading - private func fetchGroupMembers() async { + private func fetchGroupWithMembers() async { do { - let members = try await groupRepository.fetchMembersBy(groupId: groupId) - self.members = members + let group = try await groupRepository.fetchGroupBy(id: groupId) + guard let group else { + viewState = .initial + return + } + self.members = try await groupRepository.fetchMembersBy(memberIds: group.members) viewState = .initial } catch { handleServiceError() diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingView.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingView.swift index 06fb2b712..10daa2cf8 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingView.swift @@ -16,7 +16,7 @@ struct GroupWhoIsPayingView: View { var body: some View { VStack(alignment: .leading, spacing: 0) { if .noInternet == viewModel.currentViewState || .somethingWentWrong == viewModel.currentViewState { - ErrorView(isForNoInternet: viewModel.currentViewState == .noInternet, onClick: viewModel.fetchInitialMembersData) + ErrorView(isForNoInternet: viewModel.currentViewState == .noInternet, onClick: viewModel.fetchInitialViewData) } else if case .loading = viewModel.currentViewState { LoaderView() } else { @@ -41,7 +41,7 @@ struct GroupWhoIsPayingView: View { .background(surfaceColor) .toastView(toast: $viewModel.toast) .backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert) - .onAppear(perform: viewModel.fetchInitialMembersData) + .onAppear(perform: viewModel.fetchInitialViewData) .toolbarRole(.editor) .toolbar { ToolbarItem(placement: .topBarLeading) { diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingViewModel.swift index 711c899ba..802eefd22 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Who Is paying/GroupWhoIsPayingViewModel.swift @@ -28,17 +28,21 @@ class GroupWhoIsPayingViewModel: BaseViewModel, ObservableObject { super.init() } - func fetchInitialMembersData() { + func fetchInitialViewData() { Task { - await fetchGroupMembers() + await fetchGroupWithMembers() } } // MARK: - Data Loading - private func fetchGroupMembers() async { + private func fetchGroupWithMembers() async { do { - let members = try await groupRepository.fetchMembersBy(groupId: groupId) - self.members = members + let group = try await groupRepository.fetchGroupBy(id: groupId) + guard let group else { + currentViewState = .initial + return + } + self.members = try await groupRepository.fetchMembersBy(memberIds: group.members) currentViewState = .initial } catch { handleServiceError() diff --git a/Splito/UI/Home/Groups/Group/Group Options/Totals/GroupTotalsView.swift b/Splito/UI/Home/Groups/Group/Group Options/Totals/GroupTotalsView.swift index e8baf1fbf..30a961d41 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Totals/GroupTotalsView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Totals/GroupTotalsView.swift @@ -122,7 +122,7 @@ private struct GroupSummaryAmountView: View { Spacer() - Text((amount < 0 ? "-" : "") + amount.formattedCurrency) + Text(amount.formattedCurrencyWithSign) .font(.body1()) .foregroundStyle(amount == 0 ? lowestText : fontColor) } diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift index c371296dd..de8fe51d2 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift @@ -40,7 +40,7 @@ struct GroupTransactionListView: View { .toolbarRole(.editor) .toolbar { ToolbarItem(placement: .topBarLeading) { - NavigationTitleTextView(text: "Transactions") + NavigationTitleTextView(text: "Payments") } } } @@ -248,13 +248,13 @@ private struct EmptyTransactionView: View { .frame(width: geometry.size.width * 0.5, height: geometry.size.width * 0.4) .padding(.bottom, 40) - Text("No transactions yet!") + Text("No payments yet!") .font(.Header1()) .foregroundStyle(primaryText) .multilineTextAlignment(.center) .padding(.bottom, 16) - Text("Start spending or receiving money to see your transactions here.") + Text("Start spending or receiving money to see your payments here.") .font(.subTitle1()) .foregroundStyle(disableText) .tracking(-0.2) diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListViewModel.swift index 5ac7a98cd..54479e5c6 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListViewModel.swift @@ -146,8 +146,8 @@ class GroupTransactionListViewModel: BaseViewModel, ObservableObject { // MARK: - User Actions func showTransactionDeleteAlert(_ transaction: Transactions) { showAlert = true - alert = .init(title: "Delete Transaction", - message: "Are you sure you want to delete this transaction?", + alert = .init(title: "Delete payment", + message: "Are you sure you want to delete this payment?", positiveBtnTitle: "Ok", positiveBtnAction: { Task { diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift index b3b0d890e..002fa487e 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift @@ -23,8 +23,9 @@ struct GroupTransactionDetailView: View { } else { ScrollView { VStack(alignment: .center, spacing: 0) { + VSpacer(16) + TransactionInfoView(geometry: geometry, viewModel: viewModel) - .padding(.top, 16) Text("This payment was noted using the \"record a payment\" feature, No money has been transferred.") .font(.caption1()) @@ -61,7 +62,7 @@ struct GroupTransactionDetailView: View { .toolbarRole(.editor) .toolbar { ToolbarItem(placement: .topBarLeading) { - NavigationTitleTextView(text: "Transaction detail") + NavigationTitleTextView(text: "Payment detail") } if viewModel.viewState != .loading { if (viewModel.transaction?.isActive ?? false) && (viewModel.group?.isActive ?? false) { @@ -121,12 +122,15 @@ private struct TransactionInfoView: View { Image(.transactionIcon) .resizable() - .frame(width: 35, height: 36) - .padding(7) + .scaledToFit() + .frame(width: 42, height: 42) ProfileCardView(name: receiverName, imageUrl: receiverImageUrl, geometry: geometry) } .padding(16) + .frame(maxWidth: .infinity, alignment: .center) + .background(container2Color) + .cornerRadius(16) TransactionSummaryView(date: viewModel.transaction?.date.dateValue(), amount: viewModel.transaction?.amount, payerName: payerName, receiverName: receiverName, addedUserName: addedUserName) } @@ -153,10 +157,7 @@ struct ProfileCardView: View { .foregroundStyle(primaryText) .lineLimit(1) } - .padding(.horizontal, 8) - .frame(width: width * 0.3, height: 97) - .background(container2Color) - .cornerRadius(12) + .frame(width: width * 0.3, height: 87) } } @@ -182,7 +183,7 @@ private struct TransactionSummaryView: View { Divider() .frame(height: 1) - .background(dividerColor) + .background(outlineColor) .padding(.vertical, 16) Text("Added by \(addedUserName.localized) on \(date?.longDate ?? "Today")") diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift index 62dd3b5d1..4308613b5 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift @@ -113,8 +113,8 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { func handleRestoreButtonAction() { showAlert = true - alert = .init(title: "Restore transaction", - message: "Are you sure you want to restore this transaction?", + alert = .init(title: "Restore payment", + message: "Are you sure you want to restore this payment?", positiveBtnTitle: "Ok", positiveBtnAction: self.restoreTransaction, negativeBtnTitle: "Cancel", @@ -125,7 +125,7 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { guard let group, group.isActive else { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.showAlertFor(title: "Error", - message: "The group associated with this transaction has been deleted, so it cannot be restored.") + message: "The group associated with this payment has been deleted, so it cannot be restored.") } return } @@ -147,7 +147,6 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { self.transaction = try await self.transactionRepository.updateTransaction(group: group, transaction: transaction, oldTransaction: transaction, members: (payer, receiver), type: .transactionRestored) await self.updateGroupMemberBalance(updateType: .Add) - showToastFor(toast: .init(type: .success, title: "Success", message: "Transaction restored successfully.")) self.viewState = .initial self.router.pop() @@ -160,8 +159,8 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { func handleDeleteBtnAction() { showAlert = true - alert = .init(title: "Delete Transaction", - message: "Are you sure you want to delete this transaction?", + alert = .init(title: "Delete payment", + message: "Are you sure you want to delete this payment?", positiveBtnTitle: "Ok", positiveBtnAction: self.deleteTransaction, negativeBtnTitle: "Cancel", @@ -211,7 +210,7 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { guard let userId = preference.user?.id, let group, group.members.contains(userId) else { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.showAlertFor(title: "Error", - message: "This transaction could not be \(operationText). You do not have permission to \(action) this transaction, Sorry!") + message: "This payment could not be \(operationText). You do not have permission to \(action) this payment, Sorry!") } return false } diff --git a/Splito/UI/Home/Groups/Group/Group Setting/GroupSettingViewModel.swift b/Splito/UI/Home/Groups/Group/Group Setting/GroupSettingViewModel.swift index b2ce6292d..5cefe825d 100644 --- a/Splito/UI/Home/Groups/Group/Group Setting/GroupSettingViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Setting/GroupSettingViewModel.swift @@ -56,8 +56,13 @@ class GroupSettingViewModel: BaseViewModel, ObservableObject { } private func fetchGroupMembers() async { + guard let group else { + currentViewState = .initial + return + } + do { - let members = try await groupRepository.fetchMembersBy(groupId: groupId) + let members = try await groupRepository.fetchMembersBy(memberIds: group.members) sortGroupMembers(members: members) } catch { handleServiceError() diff --git a/Splito/UI/Home/Groups/Group/GroupExpenseListView.swift b/Splito/UI/Home/Groups/Group/GroupExpenseListView.swift index a8467b3af..611cc6e67 100644 --- a/Splito/UI/Home/Groups/Group/GroupExpenseListView.swift +++ b/Splito/UI/Home/Groups/Group/GroupExpenseListView.swift @@ -326,6 +326,7 @@ private struct GroupExpenseHeaderOverallView: View { Text("Your \(Date().nameOfMonth.lowercased()) spending") .font(.body3()) .foregroundStyle(disableText) + .multilineTextAlignment(.trailing) Text("\(abs(viewModel.currentMonthSpending).formattedCurrency)") .font(.body1()) diff --git a/Splito/UI/Home/Groups/Group/GroupHomeView.swift b/Splito/UI/Home/Groups/Group/GroupHomeView.swift index f416949e9..16d7b08f8 100644 --- a/Splito/UI/Home/Groups/Group/GroupHomeView.swift +++ b/Splito/UI/Home/Groups/Group/GroupHomeView.swift @@ -32,11 +32,11 @@ struct GroupHomeView: View { EmptyStateView(buttonTitle: "Add expense", geometry: geometry, onClick: viewModel.openAddExpenseSheet) } else if case .memberNotInGroup = viewModel.groupState { EmptyStateView(title: "You're no longer part of this group.", - subtitle: "You no longer have access to this group's activities, expenses and transactions.", + subtitle: "You no longer have access to this group's activities, expenses and payments.", image: .restoreGroupIcon, geometry: geometry) } else if case .deactivateGroup = viewModel.groupState { EmptyStateView(title: "This group has been deleted.", - subtitle: "You can restore it to recover all activities, expenses and transactions.", + subtitle: "You can restore it to recover all activities, expenses and payments.", buttonTitle: "Restore", image: .restoreGroupIcon, geometry: geometry, onClick: viewModel.handleRestoreGroupAction) } else if case .hasExpense = viewModel.groupState { @@ -49,7 +49,6 @@ struct GroupHomeView: View { .frame(maxWidth: isIpad ? 600 : nil, alignment: .center) .frame(maxWidth: .infinity, alignment: .center) .background(surfaceColor) - .toastView(toast: $viewModel.toast, bottomPadding: 32) .backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert) .onDisappear { if viewModel.showSearchBar { @@ -67,6 +66,7 @@ struct GroupHomeView: View { .ignoresSafeArea(.keyboard) } } + .toastView(toast: $viewModel.toast) .fullScreenCover(isPresented: $viewModel.showAddExpenseSheet) { ExpenseRouteView(selectedGroupId: viewModel.groupId) } @@ -131,7 +131,7 @@ struct GroupOptionsListView: View { HStack(spacing: 8) { GroupOptionsButtonView(text: "Settle up", isForSettleUp: isSettleUpEnable, onTap: onSettleUpTap) - GroupOptionsButtonView(text: "Transactions", onTap: onTransactionsTap) + GroupOptionsButtonView(text: "Payments", onTap: onTransactionsTap) GroupOptionsButtonView(text: "Balances", onTap: onBalanceTap) diff --git a/Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift b/Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift index 763861aee..17b04eef7 100644 --- a/Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift +++ b/Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift @@ -61,7 +61,7 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject { let router: Router var hasMoreExpenses: Bool = true - var groupUserData: [AppUser] = [] + var groupMembers: [AppUser] = [] private var lastDocument: DocumentSnapshot? init(router: Router, groupId: String) { @@ -100,8 +100,8 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject { if self.group?.members != group.members { for member in group.members where member != self.preference.user?.id { - if let memberData = await self.fetchUserData(for: member) { - self.groupUserData.append(memberData) + if let memberData = await fetchMemberData(for: member) { + addMemberIfNotExist(memberData) } } } @@ -168,9 +168,21 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject { private func combineMemberWithExpense(expenses: [Expense]) async { var combinedData: [ExpenseWithUser] = [] - for expense in expenses.uniqued() { - if let user = await fetchUserData(for: expense.paidBy.keys.first ?? "") { - combinedData.append(ExpenseWithUser(expense: expense, user: user)) + await withTaskGroup(of: ExpenseWithUser?.self) { taskGroup in + for expense in expenses.uniqued() { + taskGroup.addTask { [weak self] in + guard let self else { return nil } + if let user = await self.fetchMemberData(for: expense.paidBy.keys.first ?? "") { + return ExpenseWithUser(expense: expense, user: user) + } + return nil + } + } + + for await result in taskGroup { + if let expenseWithUser = result { + combinedData.append(expenseWithUser) + } } } @@ -180,21 +192,23 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject { } } - func fetchUserData(for userId: String) async -> AppUser? { - if let existingUser = groupUserData.first(where: { $0.id == userId }) { - return existingUser // Return the available user from groupUserData - } else { - do { - let user = try await groupRepository.fetchMemberBy(userId: userId) - if let user { - self.groupUserData.append(user) - } - return user - } catch { - groupState = .noMember - showToastForError() - return nil + func fetchMemberData(for memberId: String) async -> AppUser? { + do { + let member = try await groupRepository.fetchMemberBy(userId: memberId) + if let member { + addMemberIfNotExist(member) } + return member + } catch { + groupState = .noMember + showToastForError() + return nil + } + } + + private func addMemberIfNotExist(_ member: AppUser) { + if !groupMembers.contains(where: { $0.id == member.id }) { + groupMembers.append(member) } } diff --git a/Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift b/Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift index b01cfd97c..df1b850c9 100644 --- a/Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift +++ b/Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift @@ -12,7 +12,7 @@ import BaseStyle // MARK: - User Actions extension GroupHomeViewModel { func getMemberDataBy(id: String) -> AppUser? { - return groupUserData.first(where: { $0.id == id }) + return groupMembers.first(where: { $0.id == id }) } func handleInviteMemberClick() { @@ -92,7 +92,7 @@ extension GroupHomeViewModel { func handleRestoreGroupAction() { showAlert = true alert = .init(title: "Restore group", - message: "This will restore all activities, expenses and transactions for this group.", + message: "This will restore all activities, expenses and payments for this group.", positiveBtnTitle: "Ok", positiveBtnAction: self.restoreGroup, negativeBtnTitle: "Cancel", @@ -185,7 +185,7 @@ extension GroupHomeViewModel { Task { expenses.append(newExpense) - if let user = await fetchUserData(for: newExpense.paidBy.keys.first ?? "") { + if let user = await fetchMemberData(for: newExpense.paidBy.keys.first ?? "") { let newExpenseWithUser = ExpenseWithUser(expense: newExpense, user: user) withAnimation { expensesWithUser.append(newExpenseWithUser) @@ -203,7 +203,7 @@ extension GroupHomeViewModel { } Task { [weak self] in - if let user = await self?.fetchUserData(for: updatedExpense.paidBy.keys.first ?? "") { + if let user = await self?.fetchMemberData(for: updatedExpense.paidBy.keys.first ?? "") { if let index = self?.expensesWithUser.firstIndex(where: { $0.expense.id == updatedExpense.id }) { let updatedExpenseWithUser = ExpenseWithUser(expense: updatedExpense, user: user) withAnimation { diff --git a/Splito/UI/Home/Groups/GroupListView.swift b/Splito/UI/Home/Groups/GroupListView.swift index 786e3f7cc..9c26afc9a 100644 --- a/Splito/UI/Home/Groups/GroupListView.swift +++ b/Splito/UI/Home/Groups/GroupListView.swift @@ -70,7 +70,6 @@ struct GroupListView: View { .frame(maxWidth: isIpad ? 600 : nil, alignment: .center) .frame(maxWidth: .infinity, alignment: .center) .background(surfaceColor) - .toastView(toast: $viewModel.toast, bottomPadding: 32) .backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert) .navigationTitle("") .navigationBarTitleDisplayMode(.inline) @@ -107,6 +106,7 @@ struct GroupListView: View { .ignoresSafeArea(.keyboard) } } + .toastView(toast: $viewModel.toast) .sheet(isPresented: $viewModel.showActionSheet) { GroupActionSheetView(onSelectionWith: viewModel.handleOptionSelection(with:)) .fixedSize(horizontal: false, vertical: true) diff --git a/Splito/UI/Home/Groups/GroupListViewModel.swift b/Splito/UI/Home/Groups/GroupListViewModel.swift index e010d115d..1e6942e14 100644 --- a/Splito/UI/Home/Groups/GroupListViewModel.swift +++ b/Splito/UI/Home/Groups/GroupListViewModel.swift @@ -36,7 +36,6 @@ class GroupListViewModel: BaseViewModel, ObservableObject { let router: Router var hasMoreGroups: Bool = true private var lastDocument: DocumentSnapshot? - private var groupMembers: [AppUser] = [] var filteredGroups: [GroupInformation] { guard case .hasGroup = groupListState else { return [] } @@ -62,6 +61,7 @@ class GroupListViewModel: BaseViewModel, ObservableObject { NotificationCenter.default.addObserver(self, selector: #selector(handleDeleteGroup(notification:)), name: .deleteGroup, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleLeaveGroup(notification:)), name: .leaveGroup, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleJoinGroup(notification:)), name: .joinGroup, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(handleAddExpense(notification:)), name: .addExpense, object: nil) fetchGroupsInitialData() } @@ -134,7 +134,7 @@ class GroupListViewModel: BaseViewModel, ObservableObject { } private func fetchGroupInformation(group: Groups) async throws -> GroupInformation { - let members = try await groupRepository.fetchMembersBy(groupId: group.id ?? "") + let members = try await groupRepository.fetchMembersBy(memberIds: group.members) let userId = preference.user?.id ?? "" let memberBalance = getMembersBalance(group: group, memberId: userId) @@ -166,17 +166,6 @@ class GroupListViewModel: BaseViewModel, ObservableObject { } } - private func fetchUserData(for userId: String) async { - guard !groupMembers.contains(where: { $0.id == userId }) else { return } - do { - if let user = try await userRepository.fetchUserBy(userID: userId) { - groupMembers.append(user) - } - } catch { - showToastForError() - } - } - private func fetchGroup(groupId: String) async -> Groups? { do { return try await groupRepository.fetchGroupBy(id: groupId) @@ -342,32 +331,52 @@ extension GroupListViewModel { message: action == .deleteGroup ? "Group deleted successfully." : "Group left successfully.")) } + @objc private func handleAddExpense(notification: Notification) { + guard let expenseInfo = notification.userInfo, + let notificationGroupId = expenseInfo["groupId"] as? String else { return } + + Task { + if let existingIndex = combinedGroups.firstIndex(where: { $0.group.id == notificationGroupId }) { + if let updatedGroup = await fetchGroup(groupId: notificationGroupId) { + do { + let groupInformation = try await fetchGroupInformation(group: updatedGroup) + combinedGroups[existingIndex] = groupInformation + } catch { + showToastForError() + } + } + } + } + } + private func processGroup(group: Groups, isNewGroup: Bool) async { let userId = preference.user?.id ?? "" let memberBalance = getMembersBalance(group: group, memberId: userId) let memberOwingAmount = calculateExpensesSimplified(userId: userId, memberBalances: group.balances) - for memberId in group.members { - await fetchUserData(for: memberId) - } - - let groupInfo = GroupInformation( - group: group, - userBalance: memberBalance, - memberOweAmount: memberOwingAmount, - members: groupMembers, - hasExpenses: group.hasExpenses - ) - - if isNewGroup { - combinedGroups.insert(groupInfo, at: 0) - if combinedGroups.count == 1 { - groupListState = .hasGroup - } - } else { - if let index = combinedGroups.firstIndex(where: { $0.group.id == group.id }) { - combinedGroups[index] = groupInfo + do { + let groupMembers = try await groupRepository.fetchMembersBy(memberIds: group.members) + + let groupInfo = GroupInformation( + group: group, + userBalance: memberBalance, + memberOweAmount: memberOwingAmount, + members: groupMembers, + hasExpenses: group.hasExpenses + ) + + if isNewGroup { + combinedGroups.insert(groupInfo, at: 0) + if combinedGroups.count == 1 { + groupListState = .hasGroup + } + } else { + if let index = combinedGroups.firstIndex(where: { $0.group.id == group.id }) { + combinedGroups[index] = groupInfo + } } + } catch { + showToastForError() } } diff --git a/firebase-debug.log b/firebase-debug.log deleted file mode 100644 index f350006f0..000000000 --- a/firebase-debug.log +++ /dev/null @@ -1,494 +0,0 @@ -[debug] [2024-11-18T06:13:01.031Z] ---------------------------------------------------------------------- -[debug] [2024-11-18T06:13:01.033Z] Command: /Users/NiraliSonani/.nvm/versions/node/v18.20.4/bin/node /Users/NiraliSonani/.nvm/versions/node/v18.20.4/bin/firebase deploy --only functions -[debug] [2024-11-18T06:13:01.033Z] CLI Version: 13.23.0 -[debug] [2024-11-18T06:13:01.033Z] Platform: darwin -[debug] [2024-11-18T06:13:01.033Z] Node Version: v18.20.4 -[debug] [2024-11-18T06:13:01.037Z] Time: Mon Nov 18 2024 11:43:01 GMT+0530 (India Standard Time) -[debug] [2024-11-18T06:13:01.037Z] ---------------------------------------------------------------------- -[debug] -[debug] [2024-11-18T06:13:01.067Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2024-11-18T06:13:01.067Z] > authorizing via signed-in user (nirali.s@canopas.com) -[debug] [2024-11-18T06:13:01.067Z] [iam] checking project splito-canoaps for permissions ["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","firebase.projects.get"] -[debug] [2024-11-18T06:13:01.067Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:01.067Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:01.068Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions [none] -[debug] [2024-11-18T06:13:01.068Z] >>> [apiv2][(partial)header] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:01.068Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions {"permissions":["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","firebase.projects.get"]} -[debug] [2024-11-18T06:13:02.645Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions 200 -[debug] [2024-11-18T06:13:02.645Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions {"permissions":["cloudfunctions.functions.create","cloudfunctions.functions.delete","cloudfunctions.functions.get","cloudfunctions.functions.list","cloudfunctions.functions.update","cloudfunctions.operations.get","firebase.projects.get"]} -[debug] [2024-11-18T06:13:02.645Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:02.646Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:02.646Z] >>> [apiv2][query] POST https://iam.googleapis.com/v1/projects/splito-canoaps/serviceAccounts/splito-canoaps@appspot.gserviceaccount.com:testIamPermissions [none] -[debug] [2024-11-18T06:13:02.646Z] >>> [apiv2][body] POST https://iam.googleapis.com/v1/projects/splito-canoaps/serviceAccounts/splito-canoaps@appspot.gserviceaccount.com:testIamPermissions {"permissions":["iam.serviceAccounts.actAs"]} -[debug] [2024-11-18T06:13:04.434Z] <<< [apiv2][status] POST https://iam.googleapis.com/v1/projects/splito-canoaps/serviceAccounts/splito-canoaps@appspot.gserviceaccount.com:testIamPermissions 200 -[debug] [2024-11-18T06:13:04.435Z] <<< [apiv2][body] POST https://iam.googleapis.com/v1/projects/splito-canoaps/serviceAccounts/splito-canoaps@appspot.gserviceaccount.com:testIamPermissions {"permissions":["iam.serviceAccounts.actAs"]} -[info] -[info] === Deploying to 'splito-canoaps'... -[info] -[info] i deploying functions -[info] Running command: npm --prefix "$RESOURCE_DIR" run lint -[info] Running command: npm --prefix "$RESOURCE_DIR" run build -[info] ✔ functions: Finished running predeploy script. -[debug] [2024-11-18T06:13:09.675Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:09.676Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:09.676Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps [none] -[debug] [2024-11-18T06:13:11.066Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps 200 -[debug] [2024-11-18T06:13:11.066Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps {"projectId":"splito-canoaps","projectNumber":"668221500241","displayName":"Splito","name":"projects/splito-canoaps","resources":{"hostingSite":"splito-canoaps","storageBucket":"splito-canoaps.appspot.com","locationId":"asia-south1"},"state":"ACTIVE","etag":"1_38c17f2d-2041-4905-9549-4d61fa5c7cc7"} -[info] i functions: preparing codebase default for deployment -[info] i functions: ensuring required API cloudfunctions.googleapis.com is enabled... -[debug] [2024-11-18T06:13:11.068Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:11.069Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:11.069Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:11.069Z] Checked if tokens are valid: true, expires at: 1731912576394 -[info] i functions: ensuring required API cloudbuild.googleapis.com is enabled... -[debug] [2024-11-18T06:13:11.069Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:11.069Z] Checked if tokens are valid: true, expires at: 1731912576394 -[info] i artifactregistry: ensuring required API artifactregistry.googleapis.com is enabled... -[debug] [2024-11-18T06:13:11.070Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:11.070Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:11.070Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudfunctions.googleapis.com [none] -[debug] [2024-11-18T06:13:11.070Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudfunctions.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:11.072Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/runtimeconfig.googleapis.com [none] -[debug] [2024-11-18T06:13:11.072Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/runtimeconfig.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:11.073Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudbuild.googleapis.com [none] -[debug] [2024-11-18T06:13:11.073Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudbuild.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:11.074Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/artifactregistry.googleapis.com [none] -[debug] [2024-11-18T06:13:11.074Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/artifactregistry.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:12.992Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudbuild.googleapis.com 200 -[debug] [2024-11-18T06:13:12.992Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudbuild.googleapis.com [omitted] -[info] ✔ functions: required API cloudbuild.googleapis.com is enabled -[debug] [2024-11-18T06:13:12.993Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/runtimeconfig.googleapis.com 200 -[debug] [2024-11-18T06:13:12.993Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/runtimeconfig.googleapis.com [omitted] -[debug] [2024-11-18T06:13:13.001Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudfunctions.googleapis.com 200 -[debug] [2024-11-18T06:13:13.001Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/cloudfunctions.googleapis.com [omitted] -[info] ✔ functions: required API cloudfunctions.googleapis.com is enabled -[debug] [2024-11-18T06:13:13.004Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/artifactregistry.googleapis.com 200 -[debug] [2024-11-18T06:13:13.004Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/artifactregistry.googleapis.com [omitted] -[info] ✔ artifactregistry: required API artifactregistry.googleapis.com is enabled -[debug] [2024-11-18T06:13:13.005Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:13.005Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:13.005Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps/adminSdkConfig [none] -[debug] [2024-11-18T06:13:14.040Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps/adminSdkConfig 200 -[debug] [2024-11-18T06:13:14.041Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps/adminSdkConfig {"projectId":"splito-canoaps","storageBucket":"splito-canoaps.appspot.com","locationId":"asia-south1"} -[debug] [2024-11-18T06:13:14.041Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:14.041Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:14.042Z] >>> [apiv2][query] GET https://runtimeconfig.googleapis.com/v1beta1/projects/splito-canoaps/configs [none] -[debug] [2024-11-18T06:13:14.624Z] <<< [apiv2][status] GET https://runtimeconfig.googleapis.com/v1beta1/projects/splito-canoaps/configs 200 -[debug] [2024-11-18T06:13:14.624Z] <<< [apiv2][body] GET https://runtimeconfig.googleapis.com/v1beta1/projects/splito-canoaps/configs {} -[debug] [2024-11-18T06:13:14.625Z] Validating nodejs source -[debug] [2024-11-18T06:13:15.202Z] > [functions] package.json contents: { - "name": "functions", - "scripts": { - "lint": "eslint --ext .js,.ts .", - "build": "tsc", - "build:watch": "tsc --watch", - "serve": "npm run build && firebase emulators:start --only functions", - "shell": "npm run build && firebase functions:shell", - "start": "npm run shell", - "deploy": "firebase deploy --only functions", - "logs": "firebase functions:log" - }, - "engines": { - "node": "18" - }, - "main": "lib/index.js", - "dependencies": { - "firebase-admin": "^12.6.0", - "firebase-functions": "^6.0.1" - }, - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.12.0", - "@typescript-eslint/parser": "^5.12.0", - "eslint": "^8.9.0", - "eslint-config-google": "^0.14.0", - "eslint-plugin-import": "^2.25.4", - "firebase-functions-test": "^3.1.0", - "typescript": "^4.9.0" - }, - "private": true -} -[debug] [2024-11-18T06:13:15.202Z] Building nodejs source -[info] i functions: Loading and analyzing source code for codebase default to determine what to deploy -[debug] [2024-11-18T06:13:15.203Z] Could not find functions.yaml. Must use http discovery -[debug] [2024-11-18T06:13:15.210Z] Found firebase-functions binary at '/Users/NiraliSonani/Desktop/Splito/functions/node_modules/.bin/firebase-functions' -[info] Serving at port 8356 - -[info] {"severity":"DEBUG","message":"Firebase app already initialized"} - -[debug] [2024-11-18T06:13:15.394Z] Got response from /__/functions.yaml {"endpoints":{"onGroupWrite":{"availableMemoryMb":null,"timeoutSeconds":null,"minInstances":null,"maxInstances":null,"ingressSettings":null,"concurrency":null,"serviceAccountEmail":null,"vpc":null,"platform":"gcfv2","labels":{},"eventTrigger":{"eventType":"google.cloud.firestore.document.v1.written","eventFilters":{"database":"(default)","namespace":"(default)"},"eventFilterPathPatterns":{"document":"groups/{groupId}"},"retry":false},"entryPoint":"onGroupWrite"},"onActivityCreate":{"availableMemoryMb":null,"timeoutSeconds":null,"minInstances":null,"maxInstances":null,"ingressSettings":null,"concurrency":null,"serviceAccountEmail":null,"vpc":null,"platform":"gcfv2","labels":{},"eventTrigger":{"eventType":"google.cloud.firestore.document.v1.created","eventFilters":{"database":"(default)","namespace":"(default)"},"eventFilterPathPatterns":{"document":"users/{userId}/activity/{activityId}"},"retry":false},"entryPoint":"onActivityCreate"}},"specVersion":"v1alpha1","requiredAPIs":[],"extensions":{}} -[info] i extensions: ensuring required API firebaseextensions.googleapis.com is enabled... -[debug] [2024-11-18T06:13:15.404Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:15.404Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:15.404Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/firebaseextensions.googleapis.com [none] -[debug] [2024-11-18T06:13:15.404Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/firebaseextensions.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:17.188Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/firebaseextensions.googleapis.com 200 -[debug] [2024-11-18T06:13:17.188Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/firebaseextensions.googleapis.com [omitted] -[info] ✔ extensions: required API firebaseextensions.googleapis.com is enabled -[debug] [2024-11-18T06:13:17.188Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2024-11-18T06:13:17.189Z] > authorizing via signed-in user (nirali.s@canopas.com) -[debug] [2024-11-18T06:13:17.189Z] [iam] checking project splito-canoaps for permissions ["firebase.projects.get","firebaseextensions.instances.list"] -[debug] [2024-11-18T06:13:17.189Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:17.189Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:17.189Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions [none] -[debug] [2024-11-18T06:13:17.189Z] >>> [apiv2][(partial)header] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:17.189Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions {"permissions":["firebase.projects.get","firebaseextensions.instances.list"]} -[debug] [2024-11-18T06:13:18.639Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions 200 -[debug] [2024-11-18T06:13:18.640Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/splito-canoaps:testIamPermissions {"permissions":["firebase.projects.get","firebaseextensions.instances.list"]} -[debug] [2024-11-18T06:13:18.640Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:18.641Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:18.642Z] >>> [apiv2][query] GET https://firebaseextensions.googleapis.com/v1beta/projects/splito-canoaps/instances pageSize=100&pageToken= -[debug] [2024-11-18T06:13:20.413Z] <<< [apiv2][status] GET https://firebaseextensions.googleapis.com/v1beta/projects/splito-canoaps/instances 200 -[debug] [2024-11-18T06:13:20.413Z] <<< [apiv2][body] GET https://firebaseextensions.googleapis.com/v1beta/projects/splito-canoaps/instances {} -[info] i functions: preparing functions directory for uploading... -[info] i functions: packaged /Users/NiraliSonani/Desktop/Splito/functions (96.61 KB) for uploading -[debug] [2024-11-18T06:13:20.455Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:20.455Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:20.455Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v1/projects/splito-canoaps/locations/-/functions [none] -[debug] [2024-11-18T06:13:22.717Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v1/projects/splito-canoaps/locations/-/functions 200 -[debug] [2024-11-18T06:13:22.717Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v1/projects/splito-canoaps/locations/-/functions {} -[debug] [2024-11-18T06:13:22.717Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:22.718Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:22.718Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/-/functions filter=environment%3D%22GEN_2%22 -[debug] [2024-11-18T06:13:25.752Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/-/functions 200 -[debug] [2024-11-18T06:13:25.752Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/-/functions {"functions":[{"name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"build":"projects/668221500241/locations/us-central1/builds/ec003dd2-e693-4b21-8a76-03eb5b9af03d","runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731909759547250"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"maxInstanceCount":100,"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","updateTime":"2024-11-18T06:03:21.749345449Z","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"f24b0cb3bd62f9eb4ebd9b8e6d070d33ec459f8e"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite","createTime":"2024-09-06T06:44:15.499692692Z"},{"name":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","buildConfig":{"build":"projects/668221500241/locations/us-central1/builds/ec003dd2-e693-4b21-8a76-03eb5b9af03d","runtime":"nodejs18","entryPoint":"onActivityCreate","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onActivityCreate/function-source.zip","generation":"1731909799015430"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onActivityCreate","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onActivityCreate","LOG_EXECUTION_ID":"true"},"maxInstanceCount":100,"ingressSettings":"ALLOW_ALL","uri":"https://onactivitycreate-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"onactivitycreate-00010-rur","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/onactivitycreate-466959","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.created","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"users/{userId}/activity/{activityId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-onactivitycreate-466959-387","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","updateTime":"2024-11-18T06:03:26.249129883Z","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"f24b0cb3bd62f9eb4ebd9b8e6d070d33ec459f8e"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onActivityCreate","createTime":"2024-10-29T05:42:02.355457840Z"}]} -[debug] [2024-11-18T06:13:25.755Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:25.755Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:25.755Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:25.755Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:25.756Z] >>> [apiv2][query] GET https://firestore.googleapis.com/v1/projects/splito-canoaps/databases/(default) [none] -[debug] [2024-11-18T06:13:25.757Z] >>> [apiv2][query] GET https://firestore.googleapis.com/v1/projects/splito-canoaps/databases/(default) [none] -[debug] [2024-11-18T06:13:26.203Z] <<< [apiv2][status] GET https://firestore.googleapis.com/v1/projects/splito-canoaps/databases/(default) 200 -[debug] [2024-11-18T06:13:26.203Z] <<< [apiv2][body] GET https://firestore.googleapis.com/v1/projects/splito-canoaps/databases/(default) {"name":"projects/splito-canoaps/databases/(default)","uid":"6508de26-3cfe-4fac-9d90-62e83a51926a","createTime":"2024-02-26T14:46:06.923009Z","updateTime":"2024-02-26T14:46:06.923009Z","locationId":"asia-south1","type":"FIRESTORE_NATIVE","concurrencyMode":"PESSIMISTIC","versionRetentionPeriod":"3600s","earliestVersionTime":"2024-11-18T05:13:26.196052Z","appEngineIntegrationMode":"DISABLED","keyPrefix":"j","pointInTimeRecoveryEnablement":"POINT_IN_TIME_RECOVERY_DISABLED","deleteProtectionState":"DELETE_PROTECTION_DISABLED","etag":"ILqRrYSd5YkDMPrDoa7X3IkD"} -[debug] [2024-11-18T06:13:26.222Z] <<< [apiv2][status] GET https://firestore.googleapis.com/v1/projects/splito-canoaps/databases/(default) 200 -[debug] [2024-11-18T06:13:26.222Z] <<< [apiv2][body] GET https://firestore.googleapis.com/v1/projects/splito-canoaps/databases/(default) {"name":"projects/splito-canoaps/databases/(default)","uid":"6508de26-3cfe-4fac-9d90-62e83a51926a","createTime":"2024-02-26T14:46:06.923009Z","updateTime":"2024-02-26T14:46:06.923009Z","locationId":"asia-south1","type":"FIRESTORE_NATIVE","concurrencyMode":"PESSIMISTIC","versionRetentionPeriod":"3600s","earliestVersionTime":"2024-11-18T05:13:26.218060Z","appEngineIntegrationMode":"DISABLED","keyPrefix":"j","pointInTimeRecoveryEnablement":"POINT_IN_TIME_RECOVERY_DISABLED","deleteProtectionState":"DELETE_PROTECTION_DISABLED","etag":"IOy+roSd5YkDMPrDoa7X3IkD"} -[info] i functions: ensuring required API run.googleapis.com is enabled... -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[info] i functions: ensuring required API eventarc.googleapis.com is enabled... -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[info] i functions: ensuring required API pubsub.googleapis.com is enabled... -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[info] i functions: ensuring required API storage.googleapis.com is enabled... -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:26.225Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:26.226Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/run.googleapis.com [none] -[debug] [2024-11-18T06:13:26.226Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/run.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:26.228Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/eventarc.googleapis.com [none] -[debug] [2024-11-18T06:13:26.228Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/eventarc.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:26.230Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/pubsub.googleapis.com [none] -[debug] [2024-11-18T06:13:26.230Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/pubsub.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:26.232Z] >>> [apiv2][query] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/storage.googleapis.com [none] -[debug] [2024-11-18T06:13:26.232Z] >>> [apiv2][(partial)header] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/storage.googleapis.com x-goog-quota-user=projects/splito-canoaps -[debug] [2024-11-18T06:13:28.002Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/eventarc.googleapis.com 200 -[debug] [2024-11-18T06:13:28.002Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/eventarc.googleapis.com [omitted] -[info] ✔ functions: required API eventarc.googleapis.com is enabled -[debug] [2024-11-18T06:13:28.005Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/pubsub.googleapis.com 200 -[debug] [2024-11-18T06:13:28.006Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/pubsub.googleapis.com [omitted] -[info] ✔ functions: required API pubsub.googleapis.com is enabled -[debug] [2024-11-18T06:13:28.007Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/run.googleapis.com 200 -[debug] [2024-11-18T06:13:28.007Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/run.googleapis.com [omitted] -[info] ✔ functions: required API run.googleapis.com is enabled -[debug] [2024-11-18T06:13:28.007Z] <<< [apiv2][status] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/storage.googleapis.com 200 -[debug] [2024-11-18T06:13:28.007Z] <<< [apiv2][body] GET https://serviceusage.googleapis.com/v1/projects/splito-canoaps/services/storage.googleapis.com [omitted] -[info] ✔ functions: required API storage.googleapis.com is enabled -[info] i functions: generating the service identity for pubsub.googleapis.com... -[debug] [2024-11-18T06:13:28.008Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:28.008Z] Checked if tokens are valid: true, expires at: 1731912576394 -[info] i functions: generating the service identity for eventarc.googleapis.com... -[debug] [2024-11-18T06:13:28.008Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:28.008Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:28.008Z] >>> [apiv2][query] POST https://serviceusage.googleapis.com/v1beta1/projects/668221500241/services/pubsub.googleapis.com:generateServiceIdentity [none] -[debug] [2024-11-18T06:13:28.010Z] >>> [apiv2][query] POST https://serviceusage.googleapis.com/v1beta1/projects/668221500241/services/eventarc.googleapis.com:generateServiceIdentity [none] -[debug] [2024-11-18T06:13:29.809Z] <<< [apiv2][status] POST https://serviceusage.googleapis.com/v1beta1/projects/668221500241/services/eventarc.googleapis.com:generateServiceIdentity 200 -[debug] [2024-11-18T06:13:29.809Z] <<< [apiv2][body] POST https://serviceusage.googleapis.com/v1beta1/projects/668221500241/services/eventarc.googleapis.com:generateServiceIdentity {"name":"operations/finished.DONE_OPERATION","done":true,"response":{"@type":"type.googleapis.com/google.api.serviceusage.v1beta1.ServiceIdentity","email":"service-668221500241@gcp-sa-eventarc.iam.gserviceaccount.com","uniqueId":"100139966785879531278"}} -[debug] [2024-11-18T06:13:29.840Z] <<< [apiv2][status] POST https://serviceusage.googleapis.com/v1beta1/projects/668221500241/services/pubsub.googleapis.com:generateServiceIdentity 200 -[debug] [2024-11-18T06:13:29.840Z] <<< [apiv2][body] POST https://serviceusage.googleapis.com/v1beta1/projects/668221500241/services/pubsub.googleapis.com:generateServiceIdentity {"name":"operations/finished.DONE_OPERATION","done":true,"response":{"@type":"type.googleapis.com/google.api.serviceusage.v1beta1.ServiceIdentity","email":"service-668221500241@gcp-sa-pubsub.iam.gserviceaccount.com","uniqueId":"115278907835386553596"}} -[debug] [2024-11-18T06:13:29.844Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:29.844Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:29.845Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps [none] -[debug] [2024-11-18T06:13:30.812Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps 200 -[debug] [2024-11-18T06:13:30.812Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/splito-canoaps {"projectId":"splito-canoaps","projectNumber":"668221500241","displayName":"Splito","name":"projects/splito-canoaps","resources":{"hostingSite":"splito-canoaps","storageBucket":"splito-canoaps.appspot.com","locationId":"asia-south1"},"state":"ACTIVE","etag":"1_38c17f2d-2041-4905-9549-4d61fa5c7cc7"} -[debug] [2024-11-18T06:13:30.814Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:30.814Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:30.814Z] >>> [apiv2][query] GET https://cloudbilling.googleapis.com/v1/projects/splito-canoaps/billingInfo [none] -[debug] [2024-11-18T06:13:32.387Z] <<< [apiv2][status] GET https://cloudbilling.googleapis.com/v1/projects/splito-canoaps/billingInfo 200 -[debug] [2024-11-18T06:13:32.387Z] <<< [apiv2][body] GET https://cloudbilling.googleapis.com/v1/projects/splito-canoaps/billingInfo {"name":"projects/splito-canoaps/billingInfo","projectId":"splito-canoaps","billingAccountName":"billingAccounts/012A8E-EA0148-DB27B0","billingEnabled":true} -[debug] [2024-11-18T06:13:32.389Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:32.389Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:32.389Z] >>> [apiv2][query] POST https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions:generateUploadUrl [none] -[debug] [2024-11-18T06:13:33.860Z] <<< [apiv2][status] POST https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions:generateUploadUrl 200 -[debug] [2024-11-18T06:13:33.860Z] <<< [apiv2][body] POST https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions:generateUploadUrl {"uploadUrl":"https://storage.googleapis.com/gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com/a0537729-268a-450e-a575-fddc64f21c74.zip?GoogleAccessId=service-668221500241@gcf-admin-robot.iam.gserviceaccount.com&Expires=1731912213&Signature=YIh8GphS7zO1LqpYXsjKz4Y6zYRL%2BQPcGzO5f0HEIiouq1Fi9O95m%2BdcOPUjrQPJpKBXMl1IkaVECkhXEXrovXKJ9vAUGn9%2BDcOl6FrkPDvxRawKQPeDhnf62D8PDdFC7m1cHQoTlFQjDTQrIEo1sb1gJ%2Fnp7lXZjQW4rTGEmVmyB1MTMZz9aCG5NgDtMasN9UKdvAfHjv4uIKQrcL5n4IWH2OLzvHOSrlWWZ%2Fn%2ByWU0vRfAoTThBu6uR5uBjE8r2xidJzIRV7HGTYSEYjcxPhZ%2FBTSA0fqWAoITA04eklto81l2vxI4FRScfvhmDQlKPTqiv%2BSBtP4JB3qnzDe5wQ%3D%3D","storageSource":{"bucket":"gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com","object":"a0537729-268a-450e-a575-fddc64f21c74.zip"}} -[debug] [2024-11-18T06:13:33.862Z] >>> [apiv2][query] PUT https://storage.googleapis.com/gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com/a0537729-268a-450e-a575-fddc64f21c74.zip GoogleAccessId=service-668221500241%40gcf-admin-robot.iam.gserviceaccount.com&Expires=1731912213&Signature=YIh8GphS7zO1LqpYXsjKz4Y6zYRL%2BQPcGzO5f0HEIiouq1Fi9O95m%2BdcOPUjrQPJpKBXMl1IkaVECkhXEXrovXKJ9vAUGn9%2BDcOl6FrkPDvxRawKQPeDhnf62D8PDdFC7m1cHQoTlFQjDTQrIEo1sb1gJ%2Fnp7lXZjQW4rTGEmVmyB1MTMZz9aCG5NgDtMasN9UKdvAfHjv4uIKQrcL5n4IWH2OLzvHOSrlWWZ%2Fn%2ByWU0vRfAoTThBu6uR5uBjE8r2xidJzIRV7HGTYSEYjcxPhZ%2FBTSA0fqWAoITA04eklto81l2vxI4FRScfvhmDQlKPTqiv%2BSBtP4JB3qnzDe5wQ%3D%3D -[debug] [2024-11-18T06:13:33.862Z] >>> [apiv2][body] PUT https://storage.googleapis.com/gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com/a0537729-268a-450e-a575-fddc64f21c74.zip [stream] -[debug] [2024-11-18T06:13:35.273Z] <<< [apiv2][status] PUT https://storage.googleapis.com/gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com/a0537729-268a-450e-a575-fddc64f21c74.zip 200 -[debug] [2024-11-18T06:13:35.274Z] <<< [apiv2][body] PUT https://storage.googleapis.com/gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com/a0537729-268a-450e-a575-fddc64f21c74.zip [omitted] -[info] ✔ functions: functions folder uploaded successfully -[info] i functions: updating Node.js 18 (2nd Gen) function onGroupWrite(us-central1)... -[info] i functions: updating Node.js 18 (2nd Gen) function onActivityCreate(us-central1)... -[debug] [2024-11-18T06:13:35.281Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:35.281Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:35.282Z] >>> [apiv2][query] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onGroupWrite updateMask=name%2CbuildConfig.runtime%2CbuildConfig.entryPoint%2CbuildConfig.source.storageSource.bucket%2CbuildConfig.source.storageSource.object%2CbuildConfig.environmentVariables%2CbuildConfig.sourceToken%2CserviceConfig.environmentVariables%2CserviceConfig.ingressSettings%2CserviceConfig.timeoutSeconds%2CserviceConfig.serviceAccountEmail%2CserviceConfig.availableMemory%2CserviceConfig.minInstanceCount%2CserviceConfig.maxInstanceCount%2CserviceConfig.maxInstanceRequestConcurrency%2CserviceConfig.availableCpu%2CserviceConfig.vpcConnector%2CserviceConfig.vpcConnectorEgressSettings%2Clabels%2CeventTrigger.eventType%2CeventTrigger.retryPolicy%2CeventTrigger.eventFilters%2CeventTrigger.triggerRegion%2CbuildConfig.buildEnvironmentVariables -[debug] [2024-11-18T06:13:35.282Z] >>> [apiv2][body] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onGroupWrite {"name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com","object":"a0537729-268a-450e-a575-fddc64f21c74.zip"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""}},"serviceConfig":{"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":null,"timeoutSeconds":null,"serviceAccountEmail":null,"availableMemory":"256Mi","minInstanceCount":null,"maxInstanceCount":null,"maxInstanceRequestConcurrency":80,"availableCpu":"1","vpcConnector":null,"vpcConnectorEgressSettings":null},"labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"eventTrigger":{"eventType":"google.cloud.firestore.document.v1.written","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"triggerRegion":"asia-south1"}} -[debug] [2024-11-18T06:13:39.049Z] <<< [apiv2][status] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onGroupWrite 200 -[debug] [2024-11-18T06:13:39.049Z] <<< [apiv2][body] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onGroupWrite {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2"},"done":false} -[debug] [2024-11-18T06:13:39.050Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:39.050Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:39.051Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:13:40.464Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:13:40.464Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:13:40.967Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:13:40.968Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:40.968Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:40.968Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:13:42.383Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:13:42.383Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:13:43.385Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:13:43.386Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:43.386Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:43.386Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:13:44.885Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:13:44.885Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:13:46.886Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:13:46.886Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:46.887Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:46.887Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:13:48.291Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:13:48.291Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:13:52.292Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:13:52.293Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:52.293Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:13:52.294Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:13:53.790Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:13:53.790Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:01.791Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:14:01.792Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:01.792Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:01.792Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:14:03.233Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:14:03.233Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:13.235Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:14:13.236Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:13.236Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:13.236Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:14:14.662Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:14:14.662Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build in progress","state":"IN_PROGRESS","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:24.664Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:14:24.665Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:24.665Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:24.666Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:14:26.078Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:14:26.078Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"BUILD","message":"Build finished","state":"COMPLETE","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db","resourceUri":"https://console.cloud.google.com/cloud-build/builds;region=us-central1/af2f8d36-17d1-4084-bd0f-0bba28d9f3db?project=668221500241"},{"name":"SERVICE","message":"Updating Cloud Run service","state":"IN_PROGRESS","resource":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","resourceUri":"https://console.cloud.google.com/run/detail/us-central1/ongroupwrite?project=splito-canoaps","stateMessages":[{"severity":"INFO","type":"CloudRunServiceNewRevisionTrafficInfo","message":"A new revision will be deployed serving with 100% traffic."}]},{"name":"TRIGGER","state":"NOT_STARTED"}],"sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:26.078Z] Got source token Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE= for region us-central1 -[debug] [2024-11-18T06:14:26.078Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:26.078Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:26.079Z] >>> [apiv2][query] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onActivityCreate updateMask=name%2CbuildConfig.runtime%2CbuildConfig.entryPoint%2CbuildConfig.source.storageSource.bucket%2CbuildConfig.source.storageSource.object%2CbuildConfig.environmentVariables%2CbuildConfig.sourceToken%2CserviceConfig.environmentVariables%2CserviceConfig.ingressSettings%2CserviceConfig.timeoutSeconds%2CserviceConfig.serviceAccountEmail%2CserviceConfig.availableMemory%2CserviceConfig.minInstanceCount%2CserviceConfig.maxInstanceCount%2CserviceConfig.maxInstanceRequestConcurrency%2CserviceConfig.availableCpu%2CserviceConfig.vpcConnector%2CserviceConfig.vpcConnectorEgressSettings%2Clabels%2CeventTrigger.eventType%2CeventTrigger.retryPolicy%2CeventTrigger.eventFilters%2CeventTrigger.triggerRegion%2CbuildConfig.buildEnvironmentVariables -[debug] [2024-11-18T06:14:26.079Z] >>> [apiv2][body] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onActivityCreate {"name":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","buildConfig":{"runtime":"nodejs18","entryPoint":"onActivityCreate","source":{"storageSource":{"bucket":"gcf-v2-uploads-668221500241.us-central1.cloudfunctions.appspot.com","object":"a0537729-268a-450e-a575-fddc64f21c74.zip"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE="},"serviceConfig":{"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onActivityCreate","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onActivityCreate","LOG_EXECUTION_ID":"true"},"ingressSettings":null,"timeoutSeconds":null,"serviceAccountEmail":null,"availableMemory":"256Mi","minInstanceCount":null,"maxInstanceCount":null,"maxInstanceRequestConcurrency":80,"availableCpu":"1","vpcConnector":null,"vpcConnectorEgressSettings":null},"labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"eventTrigger":{"eventType":"google.cloud.firestore.document.v1.created","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"users/{userId}/activity/{activityId}","operator":"match-path-pattern"}],"triggerRegion":"asia-south1"}} -[debug] [2024-11-18T06:14:29.838Z] <<< [apiv2][status] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onActivityCreate 200 -[debug] [2024-11-18T06:14:29.839Z] <<< [apiv2][body] PATCH https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/functions/onActivityCreate {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:14:29.696082939Z","target":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","verb":"update","cancelRequested":false,"apiVersion":"v2"},"done":false} -[debug] [2024-11-18T06:14:29.839Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:29.839Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:29.840Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e [none] -[debug] [2024-11-18T06:14:31.228Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e 200 -[debug] [2024-11-18T06:14:31.229Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:14:29.696082939Z","target":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","buildConfig":{"runtime":"nodejs18","entryPoint":"onActivityCreate","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onActivityCreate/function-source.zip","generation":"1731910469598357"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onActivityCreate","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onActivityCreate","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://onactivitycreate-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"onactivitycreate-00010-rur","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/onactivitycreate-466959","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.created","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"users/{userId}/activity/{activityId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-onactivitycreate-466959-387","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onActivityCreate"},"stages":[{"name":"BUILD","message":"Reusing build","state":"COMPLETE","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},{"name":"SERVICE","message":"Updating Cloud Run service","state":"IN_PROGRESS","resource":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","resourceUri":"https://console.cloud.google.com/run/detail/us-central1/onactivitycreate?project=splito-canoaps","stateMessages":[{"severity":"INFO","type":"CloudRunServiceNewRevisionTrafficInfo","message":"A new revision will be deployed serving with 100% traffic."}]},{"name":"TRIGGER","state":"NOT_STARTED"}],"sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:31.229Z] Got source token Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE= for region us-central1 -[debug] [2024-11-18T06:14:31.730Z] [update-default-us-central1-onActivityCreate] Retrying task index 0 -[debug] [2024-11-18T06:14:31.731Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:31.731Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:31.731Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e [none] -[debug] [2024-11-18T06:14:33.144Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e 200 -[debug] [2024-11-18T06:14:33.145Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:14:29.696082939Z","target":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","buildConfig":{"runtime":"nodejs18","entryPoint":"onActivityCreate","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onActivityCreate/function-source.zip","generation":"1731910469598357"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onActivityCreate","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onActivityCreate","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://onactivitycreate-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"onactivitycreate-00010-rur","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/onactivitycreate-466959","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.created","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"users/{userId}/activity/{activityId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-onactivitycreate-466959-387","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onActivityCreate"},"stages":[{"name":"BUILD","message":"Reusing build","state":"COMPLETE","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},{"name":"SERVICE","message":"Updating Cloud Run service","state":"IN_PROGRESS","resource":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","resourceUri":"https://console.cloud.google.com/run/detail/us-central1/onactivitycreate?project=splito-canoaps","stateMessages":[{"severity":"INFO","type":"CloudRunServiceNewRevisionTrafficInfo","message":"A new revision will be deployed serving with 100% traffic."}]},{"name":"TRIGGER","state":"NOT_STARTED"}],"sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:33.146Z] Got source token Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE= for region us-central1 -[debug] [2024-11-18T06:14:34.147Z] [update-default-us-central1-onActivityCreate] Retrying task index 0 -[debug] [2024-11-18T06:14:34.148Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:34.148Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:34.148Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e [none] -[debug] [2024-11-18T06:14:35.560Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e 200 -[debug] [2024-11-18T06:14:35.560Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:14:29.696082939Z","target":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","buildConfig":{"runtime":"nodejs18","entryPoint":"onActivityCreate","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onActivityCreate/function-source.zip","generation":"1731910469598357"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onActivityCreate","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onActivityCreate","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://onactivitycreate-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"onactivitycreate-00010-rur","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/onactivitycreate-466959","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.created","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"users/{userId}/activity/{activityId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-onactivitycreate-466959-387","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onActivityCreate"},"stages":[{"name":"BUILD","message":"Reusing build","state":"COMPLETE","resource":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},{"name":"SERVICE","message":"Updating Cloud Run service","state":"IN_PROGRESS","resource":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","resourceUri":"https://console.cloud.google.com/run/detail/us-central1/onactivitycreate?project=splito-canoaps","stateMessages":[{"severity":"INFO","type":"CloudRunServiceNewRevisionTrafficInfo","message":"A new revision will be deployed serving with 100% traffic."}]},{"name":"TRIGGER","state":"NOT_STARTED"}],"sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","operationType":"UPDATE_FUNCTION","buildName":"projects/668221500241/locations/us-central1/builds/af2f8d36-17d1-4084-bd0f-0bba28d9f3db"},"done":false} -[debug] [2024-11-18T06:14:35.560Z] Got source token Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE= for region us-central1 -[debug] [2024-11-18T06:14:36.079Z] [update-default-us-central1-onGroupWrite] Retrying task index 0 -[debug] [2024-11-18T06:14:36.080Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:36.080Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:36.080Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 [none] -[debug] [2024-11-18T06:14:37.487Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 200 -[debug] [2024-11-18T06:14:37.488Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439 {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910416580-62729d129bdd6-ffd27d30-a9c7d439","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:13:38.907288801Z","endTime":"2024-11-18T06:14:32.591332597Z","target":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onGroupWrite","buildConfig":{"runtime":"nodejs18","entryPoint":"onGroupWrite","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onGroupWrite/function-source.zip","generation":"1731910418850872"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/ongroupwrite","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onGroupWrite","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onGroupWrite","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://ongroupwrite-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"ongroupwrite-00015-biw","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/ongroupwrite-055925","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.written","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"groups/{groupId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-ongroupwrite-055925-400","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onGroupWrite"},"stages":[{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION"},"done":true,"error":{"code":3,"message":"Could not create or update Cloud Run service ongroupwrite, Container Healthcheck failed. Revision 'ongroupwrite-00016-xiq' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/ongroupwrite/revision_name/ongroupwrite-00016-xiq&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22ongroupwrite%22%0Aresource.labels.revision_name%3D%22ongroupwrite-00016-xiq%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start"}} -[debug] [2024-11-18T06:14:37.488Z] Got source token undefined for region us-central1 -[error] Could not create or update Cloud Run service ongroupwrite, Container Healthcheck failed. Revision 'ongroupwrite-00016-xiq' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information. - -Logs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/ongroupwrite/revision_name/ongroupwrite-00016-xiq&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22ongroupwrite%22%0Aresource.labels.revision_name%3D%22ongroupwrite-00016-xiq%22 -For more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start -[debug] [2024-11-18T06:14:37.561Z] [update-default-us-central1-onActivityCreate] Retrying task index 0 -[debug] [2024-11-18T06:14:37.562Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:37.562Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:37.562Z] >>> [apiv2][query] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e [none] -[debug] [2024-11-18T06:14:38.995Z] <<< [apiv2][status] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e 200 -[debug] [2024-11-18T06:14:38.995Z] <<< [apiv2][body] GET https://cloudfunctions.googleapis.com/v2/projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e {"name":"projects/splito-canoaps/locations/us-central1/operations/operation-1731910467362-62729d4309f80-3f94afae-cbdc7b0e","metadata":{"@type":"type.googleapis.com/google.cloud.functions.v2.OperationMetadata","createTime":"2024-11-18T06:14:29.696082939Z","endTime":"2024-11-18T06:14:36.330125798Z","target":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","verb":"update","cancelRequested":false,"apiVersion":"v2","requestResource":{"@type":"type.googleapis.com/google.cloud.functions.v2.Function","name":"projects/splito-canoaps/locations/us-central1/functions/onActivityCreate","buildConfig":{"runtime":"nodejs18","entryPoint":"onActivityCreate","source":{"storageSource":{"bucket":"gcf-v2-sources-668221500241-us-central1","object":"onActivityCreate/function-source.zip","generation":"1731910469598357"}},"environmentVariables":{"GOOGLE_NODE_RUN_SCRIPTS":""},"dockerRepository":"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts","sourceToken":"Cldwcm9qZWN0cy82NjgyMjE1MDAyNDEvbG9jYXRpb25zL3VzLWNlbnRyYWwxL2J1aWxkcy9hZjJmOGQzNi0xN2QxLTQwODQtYmQwZi0wYmJhMjhkOWYzZGISb3VzLWNlbnRyYWwxLWRvY2tlci5wa2cuZGV2L3NwbGl0by1jYW5vYXBzL2djZi1hcnRpZmFjdHMvc3BsaXRvLS1jYW5vYXBzX191cy0tY2VudHJhbDFfX29uX2dyb3VwX3dyaXRlOnZlcnNpb25fMRjR1uuouRMiRHByb2plY3RzL3NwbGl0by1jYW5vYXBzL2xvY2F0aW9ucy91cy1jZW50cmFsMS9mdW5jdGlvbnMvb25Hcm91cFdyaXRlKgwIvrbruQYQmJLevAEyCG5vZGVqczE4OnYKI2djci5pby9nYWUtcnVudGltZXMvbm9kZWpzMTg6c3RhYmxlEk91cy1jZW50cmFsMS1kb2NrZXIucGtnLmRldi9zZXJ2ZXJsZXNzLXJ1bnRpbWVzL2dvb2dsZS0yMi1mdWxsL3J1bnRpbWVzL25vZGVqczE4QAE=","serviceAccount":"projects/splito-canoaps/serviceAccounts/668221500241-compute@developer.gserviceaccount.com","automaticUpdatePolicy":{}},"serviceConfig":{"service":"projects/splito-canoaps/locations/us-central1/services/onactivitycreate","timeoutSeconds":60,"environmentVariables":{"FIREBASE_CONFIG":"{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}","GCLOUD_PROJECT":"splito-canoaps","EVENTARC_CLOUD_EVENT_SOURCE":"projects/splito-canoaps/locations/us-central1/services/onActivityCreate","FUNCTION_SIGNATURE_TYPE":"cloudevent","FUNCTION_TARGET":"onActivityCreate","LOG_EXECUTION_ID":"true"},"ingressSettings":"ALLOW_ALL","uri":"https://onactivitycreate-z5zhj42rrq-uc.a.run.app","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","availableMemory":"256Mi","allTrafficOnLatestRevision":true,"revision":"onactivitycreate-00010-rur","maxInstanceRequestConcurrency":80,"availableCpu":"1"},"eventTrigger":{"trigger":"projects/splito-canoaps/locations/asia-south1/triggers/onactivitycreate-466959","triggerRegion":"asia-south1","eventType":"google.cloud.firestore.document.v1.created","eventFilters":[{"attribute":"database","value":"(default)"},{"attribute":"namespace","value":"(default)"},{"attribute":"document","value":"users/{userId}/activity/{activityId}","operator":"match-path-pattern"}],"pubsubTopic":"projects/splito-canoaps/topics/eventarc-asia-south1-onactivitycreate-466959-387","serviceAccountEmail":"668221500241-compute@developer.gserviceaccount.com","retryPolicy":"RETRY_POLICY_DO_NOT_RETRY"},"state":"ACTIVE","labels":{"deployment-tool":"cli-firebase","firebase-functions-hash":"b6c14df32b38bc540373c874c23a22dc5735d7e0"},"environment":"GEN_2","url":"https://us-central1-splito-canoaps.cloudfunctions.net/onActivityCreate"},"stages":[{"name":"SERVICE","state":"NOT_STARTED"},{"name":"TRIGGER","state":"NOT_STARTED"}],"operationType":"UPDATE_FUNCTION"},"done":true,"error":{"code":3,"message":"Could not create or update Cloud Run service onactivitycreate, Container Healthcheck failed. Revision 'onactivitycreate-00011-tew' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/onactivitycreate/revision_name/onactivitycreate-00011-tew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22onactivitycreate%22%0Aresource.labels.revision_name%3D%22onactivitycreate-00011-tew%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start"}} -[debug] [2024-11-18T06:14:38.996Z] Got source token undefined for region us-central1 -[error] Could not create or update Cloud Run service onactivitycreate, Container Healthcheck failed. Revision 'onactivitycreate-00011-tew' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information. - -Logs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/onactivitycreate/revision_name/onactivitycreate-00011-tew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22onactivitycreate%22%0Aresource.labels.revision_name%3D%22onactivitycreate-00011-tew%22 -For more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start -[debug] [2024-11-18T06:14:39.005Z] Total Function Deployment time: 63718 -[debug] [2024-11-18T06:14:39.005Z] 2 Functions Deployed -[debug] [2024-11-18T06:14:39.005Z] 2 Functions Errored -[debug] [2024-11-18T06:14:39.005Z] 0 Function Deployments Aborted -[debug] [2024-11-18T06:14:39.005Z] Average Function Deployment time: 62963 -[info] -[info] Functions deploy had errors with the following functions: - onActivityCreate(us-central1) - onGroupWrite(us-central1) -[info] i functions: cleaning up build files... -[debug] [2024-11-18T06:14:39.237Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:39.237Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:39.237Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:39.237Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:39.238Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:39.238Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:39.238Z] >>> [apiv2][query] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_group_write [none] -[debug] [2024-11-18T06:14:39.240Z] >>> [apiv2][query] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_activity_create [none] -[debug] [2024-11-18T06:14:39.241Z] >>> [apiv2][query] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list [none] -[debug] [2024-11-18T06:14:40.045Z] <<< [apiv2][status] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list 404 -[debug] [2024-11-18T06:14:40.045Z] <<< [apiv2][body] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list {"errors":[{"code":"NAME_UNKNOWN","message":"Repository \"us.gcr.io\" not found"}]} -[debug] [2024-11-18T06:14:40.046Z] Failed docker command with error Request to https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list had HTTP Error: 404, Not Found {"name":"FirebaseError","children":[],"context":{"body":{"errors":[{"code":"NAME_UNKNOWN","message":"Repository \"us.gcr.io\" not found"}],"error":{"message":"Not Found"}},"response":{"statusCode":404}},"exit":1,"message":"Request to https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list had HTTP Error: 404, Not Found","status":404} -[debug] [2024-11-18T06:14:40.047Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:40.047Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:40.047Z] >>> [apiv2][query] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list [none] -[debug] [2024-11-18T06:14:40.624Z] <<< [apiv2][status] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list 404 -[debug] [2024-11-18T06:14:40.625Z] <<< [apiv2][body] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list {"errors":[{"code":"NAME_UNKNOWN","message":"Repository \"us.gcr.io\" not found"}]} -[debug] [2024-11-18T06:14:40.625Z] Failed docker command with error Request to https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list had HTTP Error: 404, Not Found {"name":"FirebaseError","children":[],"context":{"body":{"errors":[{"code":"NAME_UNKNOWN","message":"Repository \"us.gcr.io\" not found"}],"error":{"message":"Not Found"}},"response":{"statusCode":404}},"exit":1,"message":"Request to https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list had HTTP Error: 404, Not Found","status":404} -[debug] [2024-11-18T06:14:40.727Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:40.727Z] Checked if tokens are valid: true, expires at: 1731912576394 -[debug] [2024-11-18T06:14:40.728Z] >>> [apiv2][query] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list [none] -[debug] [2024-11-18T06:14:40.742Z] <<< [apiv2][status] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_group_write 404 -[debug] [2024-11-18T06:14:40.742Z] <<< [apiv2][body] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_group_write {"error":{"code":404,"message":"Package \"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_group_write\" was not found.","status":"NOT_FOUND"}} -[debug] [2024-11-18T06:14:40.747Z] <<< [apiv2][status] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_activity_create 404 -[debug] [2024-11-18T06:14:40.747Z] <<< [apiv2][body] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_activity_create {"error":{"code":404,"message":"Package \"projects/splito-canoaps/locations/us-central1/repositories/gcf-artifacts/packages/on_activity_create\" was not found.","status":"NOT_FOUND"}} -[debug] [2024-11-18T06:14:41.283Z] <<< [apiv2][status] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list 404 -[debug] [2024-11-18T06:14:41.284Z] <<< [apiv2][body] GET https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list {"errors":[{"code":"NAME_UNKNOWN","message":"Repository \"us.gcr.io\" not found"}]} -[debug] [2024-11-18T06:14:41.284Z] Failed docker command with error Request to https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list had HTTP Error: 404, Not Found {"name":"FirebaseError","children":[],"context":{"body":{"errors":[{"code":"NAME_UNKNOWN","message":"Repository \"us.gcr.io\" not found"}],"error":{"message":"Not Found"}},"response":{"statusCode":404}},"exit":1,"message":"Request to https://us.gcr.io/v2/splito-canoaps/gcf/us-central1/tags/list had HTTP Error: 404, Not Found","status":404} -[warn] ⚠ functions: Unhandled error cleaning up build images. This could result in a small monthly bill if not corrected. You can attempt to delete these images by redeploying or you can delete them manually at https://console.cloud.google.com/gcr/images/splito-canoaps/us/gcf -[debug] [2024-11-18T06:14:41.285Z] Functions deploy failed. -[debug] [2024-11-18T06:14:41.285Z] { - "endpoint": { - "id": "onGroupWrite", - "project": "splito-canoaps", - "region": "us-central1", - "entryPoint": "onGroupWrite", - "platform": "gcfv2", - "runtime": "nodejs18", - "eventTrigger": { - "eventType": "google.cloud.firestore.document.v1.written", - "retry": false, - "eventFilters": { - "database": "(default)", - "namespace": "(default)" - }, - "eventFilterPathPatterns": { - "document": "groups/{groupId}" - }, - "region": "asia-south1" - }, - "labels": { - "deployment-tool": "cli-firebase" - }, - "ingressSettings": null, - "availableMemoryMb": null, - "serviceAccount": null, - "timeoutSeconds": null, - "maxInstances": null, - "minInstances": null, - "concurrency": 80, - "vpc": null, - "environmentVariables": { - "FIREBASE_CONFIG": "{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}", - "GCLOUD_PROJECT": "splito-canoaps", - "EVENTARC_CLOUD_EVENT_SOURCE": "projects/splito-canoaps/locations/us-central1/services/onGroupWrite", - "FUNCTION_SIGNATURE_TYPE": "cloudevent", - "FUNCTION_TARGET": "onGroupWrite", - "LOG_EXECUTION_ID": "true" - }, - "codebase": "default", - "runServiceId": "ongroupwrite", - "cpu": 1, - "securityLevel": "SECURE_ALWAYS", - "targetedByOnly": false, - "hash": "b6c14df32b38bc540373c874c23a22dc5735d7e0" - }, - "op": "update", - "original": { - "name": "FirebaseError", - "children": [], - "exit": 1, - "message": "Could not create or update Cloud Run service ongroupwrite, Container Healthcheck failed. Revision 'ongroupwrite-00016-xiq' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/ongroupwrite/revision_name/ongroupwrite-00016-xiq&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22ongroupwrite%22%0Aresource.labels.revision_name%3D%22ongroupwrite-00016-xiq%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start", - "original": { - "code": 3, - "message": "Could not create or update Cloud Run service ongroupwrite, Container Healthcheck failed. Revision 'ongroupwrite-00016-xiq' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/ongroupwrite/revision_name/ongroupwrite-00016-xiq&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22ongroupwrite%22%0Aresource.labels.revision_name%3D%22ongroupwrite-00016-xiq%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start" - }, - "status": 3, - "code": 3 - } -} -[debug] [2024-11-18T06:14:41.285Z] { - "endpoint": { - "id": "onActivityCreate", - "project": "splito-canoaps", - "region": "us-central1", - "entryPoint": "onActivityCreate", - "platform": "gcfv2", - "runtime": "nodejs18", - "eventTrigger": { - "eventType": "google.cloud.firestore.document.v1.created", - "retry": false, - "eventFilters": { - "database": "(default)", - "namespace": "(default)" - }, - "eventFilterPathPatterns": { - "document": "users/{userId}/activity/{activityId}" - }, - "region": "asia-south1" - }, - "labels": { - "deployment-tool": "cli-firebase" - }, - "ingressSettings": null, - "availableMemoryMb": null, - "serviceAccount": null, - "timeoutSeconds": null, - "maxInstances": null, - "minInstances": null, - "concurrency": 80, - "vpc": null, - "environmentVariables": { - "FIREBASE_CONFIG": "{\"projectId\":\"splito-canoaps\",\"storageBucket\":\"splito-canoaps.appspot.com\",\"locationId\":\"asia-south1\"}", - "GCLOUD_PROJECT": "splito-canoaps", - "EVENTARC_CLOUD_EVENT_SOURCE": "projects/splito-canoaps/locations/us-central1/services/onActivityCreate", - "FUNCTION_SIGNATURE_TYPE": "cloudevent", - "FUNCTION_TARGET": "onActivityCreate", - "LOG_EXECUTION_ID": "true" - }, - "codebase": "default", - "runServiceId": "onactivitycreate", - "cpu": 1, - "securityLevel": "SECURE_ALWAYS", - "targetedByOnly": false, - "hash": "b6c14df32b38bc540373c874c23a22dc5735d7e0" - }, - "op": "update", - "original": { - "name": "FirebaseError", - "children": [], - "exit": 1, - "message": "Could not create or update Cloud Run service onactivitycreate, Container Healthcheck failed. Revision 'onactivitycreate-00011-tew' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/onactivitycreate/revision_name/onactivitycreate-00011-tew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22onactivitycreate%22%0Aresource.labels.revision_name%3D%22onactivitycreate-00011-tew%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start", - "original": { - "code": 3, - "message": "Could not create or update Cloud Run service onactivitycreate, Container Healthcheck failed. Revision 'onactivitycreate-00011-tew' is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable within the allocated timeout. This can happen when the container port is misconfigured or if the timeout is too short. The health check timeout can be extended. Logs for this revision might contain more information.\n\nLogs URL: https://console.cloud.google.com/logs/viewer?project=splito-canoaps&resource=cloud_run_revision/service_name/onactivitycreate/revision_name/onactivitycreate-00011-tew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22onactivitycreate%22%0Aresource.labels.revision_name%3D%22onactivitycreate-00011-tew%22 \nFor more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start" - }, - "status": 3, - "code": 3 - } -} -[error] Error: There was an error deploying functions: -[error] - Error Failed to update function onGroupWrite in region us-central1 -[error] - Error Failed to update function onActivityCreate in region us-central1 diff --git a/functions/lint b/functions/lint new file mode 100644 index 000000000..36e5b8e01 --- /dev/null +++ b/functions/lint @@ -0,0 +1,15 @@ +> eslint --ext .js,.ts . + +Running command: npm --prefix "$RESOURCE_DIR" run build + +> build +> tsc + +✔ functions: Finished running predeploy script. +i functions: preparing codebase default for deployment +i functions: ensuring required API cloudfunctions.googleapis.com is enabled... +i functions: ensuring required API cloudbuild.googleapis.com is enabled... +i artifactregistry: ensuring required API artifactregistry.googleapis.com is enabled... +✔ functions: required API cloudbuild.googleapis.com is enabled +✔ functions: required API cloudfunctions.googleapis.com is enabled +✔ artifactregistry: required API artifactregistry.googleapis.com is enabled diff --git a/functions/src/users_service/users_service.ts b/functions/src/users_service/users_service.ts index d6e2c1930..66b806cf0 100644 --- a/functions/src/users_service/users_service.ts +++ b/functions/src/users_service/users_service.ts @@ -44,6 +44,7 @@ export const onGroupWrite = onDocumentWritten( const updatedBalances = afterData.balances || []; // Iterate through each member's balance and update their totalOweAmount + const batch = db.batch(); for (const updatedBalance of updatedBalances) { const userId = updatedBalance.id; const userDocRef = db.collection('users').doc(userId); @@ -67,16 +68,20 @@ export const onGroupWrite = onDocumentWritten( const newTotalOweAmount = (userData.total_owe_amount || 0) + diffAmount; logger.info(`Updating user ${userId} with new totalOweAmount:`, newTotalOweAmount); - // Update user's totalOweAmount field - await userDocRef.update({ + // Batch the user's totalOweAmount update + batch.update(userDocRef, { total_owe_amount: newTotalOweAmount, }); - + logger.info(`Successfully updated user ${userId}'s totalOweAmount.`); } else { logger.warn(`User document does not exist for userId: ${userId}`); } } + + // Commit the batched updates + await batch.commit(); + logger.info('Successfully committed all updates.'); } else { logger.info('No change in balances field detected.'); }