0

In a tableView I have a list of jobs. These jobs can be accessed by multiple users, therefore I need to use FIRTransaction. Based on the result of the first write to FirebaseDatabase, I need to write/not write to another path in Firebase. The schema is as follows:

//Claim job by - Cleaner
  //cleaner tries to claim booking at Users/UID/cus/bookingNumber
      //if FIRMutableData contains a key ‘claimed’ or key:value “claimed”:true 
        //update at Users/UID/cus/bookingNumber with key:value

    //based on response received write or not to another path
       //write to Cleaners/UID/bookingNumber  
            //key:value

If the internet connection drops before client app receives response from firebase server, write to Cleaners/UID/bookingNumber will not be made. How can I solve this problem?

 @IBAction func claimJob(_ sender: Any) {

     dbRef.runTransactionBlock({ (_ currentData:FIRMutableData) -> FIRTransactionResult in

  //if valueRetrieved is nil abort
   guard let val = currentData.value as? [String : AnyObject] else {
    return FIRTransactionResult.abort()
    }
           self.valueRetrieved = val

  guard let uid = FIRAuth.auth()?.currentUser?.uid else {
      print("abort no uid line 80")
         return FIRTransactionResult.abort()
        }
              self.uid = uid


     for key in self.valueRetrieved.keys {

     //unwrap value of 'claimed' key
      guard let keyValue = self.valueRetrieved["Claimed"] as? String else {
        print("abort line 88")
               return FIRTransactionResult.abort()
          }

           //check if key value is true
               if keyValue == "true"{

                //booking already assigned show alert,stop transaction 
                self.alertText = "Booking already taken, please refresh table!"
                  self.alertActionTitle = "OK"
                     self.segueIdentifier = "unwindfromClaimDetailToClaim"
                        self.showAlert()
                  return FIRTransactionResult.abort()

            } else {
              //write the new values to firebase
               let newData =  self.createDictionary()
                 currentData.value = newData
                   return FIRTransactionResult.success(withValue: currentData)

      }//end of else
}//end of for key in self

         return FIRTransactionResult.abort()

    }) {(error, committed,snapshot) in

        if let error = error {
            //display an alert with the error, ask user to try again

         self.alertText = "Booking could not be claimed, please try again."
             self.alertActionTitle = "OK"
               self.segueIdentifier = "unwindfromClaimDetailToClaim"
                  self.showAlert()


            //what if internet connection drops here or client quits app ????????????
        } else if committed == true {

           //write to Cleaners/UID/bookingNumber

            //what if internet connection drops here or client quits app??????
              self.cleanersRef.setValue(snapshot?.value)

        self.alertText = "Booking claimed.Please check your calendar"
            self.alertActionTitle = "OK"
            self.segueIdentifier = "unwindfromClaimDetailToClaim"
              self.showAlert()
        }
    }

}//end of claimJob button
KENdi
  • 7,576
  • 2
  • 16
  • 31
bibscy
  • 2,598
  • 4
  • 34
  • 82
  • Sometimes transactions are just not the right solution. See [this post](https://stackoverflow.com/questions/38111370/when-should-you-use-firebase-transactions) from @frankvanpuffelen which provides some good insight. One alternative is record-locking; all can read and write by the user that locked the record. It will 'auto-unlock' in case of client disconnection by leveraging the isConnected Firebase node. See my answer the [this question](https://stackoverflow.com/questions/37218211/firebase-connection-manager-should-return-only-one-result/37227399#37227399) for some example isConnected code. – Jay Jul 24 '17 at 16:57
  • @Jay I have asked another question and ended up giving myself an answer, but I am not sure if if I could more efficiently solve the problem client side using firebase. https://stackoverflow.com/questions/45508007 .Many thanks for your help – bibscy Aug 09 '17 at 20:57

0 Answers0