6 Replies Latest reply on Oct 8, 2013 6:35 PM by victorvodka

    trouble with withWriteAccessDo

    victorvodka

      I'm trying to create and add a keyword and I'm consistently getting

       

      LrCatalog:withWriteAccessDo: could not execute action 'SetKeywords'. It was blocked by another write access call, and no timeout parameters were provided.

       

      my code looks like this

       

       

           import 'LrTasks'.startAsyncTask( 
                                                        
                                                             LrCatalog:withWriteAccessDo('SetKeywords',
                                         
                                                             function(context)
                                                                  local myKeyword = catalog:createKeyword( 'XYZA: test', {}, true, nil  )
                                                                  photo:addKeyword(myKeyword )
                                                             end
                                                        )
           

       

       

       


      How would I even provide a timeout parameter or is that a red herring? (apologies for the way this code looks but i cannot figure out this wysiwyg editor and  i just want to insert code)

        • 1. Re: trouble with withWriteAccessDo
          areohbee Level 5

          To insert code, go into HTML mode and wrap with <pre> and </pre>.

           

          My experience: timeout parameter (introduced in Lr4) is buggy. I reverted all of my (problematic, due to migration to use new timeout parameter) code back to using Lr3-compatible access contention arbitration and haven't had a problem since.

           

          See method Catalog:update in Elare Plugin Framework.

           

          The other possibility: you are re-entering the same code twice (or in any case attempting access from two async tasks), thus you are competing with yourself for access, in which case you need recurstion guarding or something.

           

          Beware: some functions require exiting the with-do function to commit changes, before you can do things that depend on those changes being commited. Thus the reason Catalog:update supports multi-phase updating.

           

          Rob

          • 2. Re: trouble with withWriteAccessDo
            victorvodka Level 1

            if i wanted to try a withWriteAccessDo timeout, how would i?  right now i'm not sure how to save keywords without it. how would i be able to debug ongoing write access calls that might be in conflict with my keyword saving one?  none of my code other code is doing anything but reading the catalog.

            • 3. Re: trouble with withWriteAccessDo
              areohbee Level 5

              Didn't you start from SQLiteroom? (or am I thinking of somebody else). If so, just look at Catalog:update - it has calls to the with-do's that utilize the new timeout parameter, granted: they're all bypassed at this point, but they're still there, e.g.

                      if app:lrVersion() < 4444444 then -- ###3 Lr4 timeout handling is buggy - catastrophically in my case, sincing phasing progression depends on reliable/consistent error handling,
                          -- otherwise it gets stuck in a loop continuing to re-call cat access method, when it should be aborting, since internal error is not being trapped...
               

              the else clause contains the code for what used to be done if lr-version = 4 or 5 (i.e. uses the new timeout parameters).

               

              Also, have you read the SDK API doc? is it not clear?...

               

              Rob

              • 4. Re: trouble with withWriteAccessDo
                victorvodka Level 1

                yes, i'm the sqliteroom guy i think. it seems i was looking at an older copy of the documention (on RobCole.com no less) and it didn't mention the timeout table. i've found it in a more up to date version of the SDK docs.  now i'm getting a different error: Yielding not allowed within a C or metamethod call.  i thought that error was supposed to go away when i used LrTasks. here's the code now:

                 

                          f:push_button
                                              {
                                                   bind_to_object = dialogData,
                                                   title="Save Keywords", 
                                                   action= Debug.showErrors (function( button )
                                                                  
                                                                  LrTasks:startAsyncTask( 
                                                                  
                                                                       catalog:withWriteAccessDo( 'SetKeywords',
                                                   
                                                                       function(context)
                                                                            local myKeyword = Catalog:createKeyword( 'XYZA: test', {}, true, nil  )
                                                                            photo:addKeyword(myKeyword )
                                                                       end
                                                                       , {timeout=32}
                                                                  )
                                                             )
                                                             
                                                             
                                                             
                                                        end)
                                                        ,
                                                   visible=true
                                     
                                              },
                
                1 person found this helpful
                • 5. Re: trouble with withWriteAccessDo
                  areohbee Level 5

                  You don't want the Debug.showErrors to wrap the LrTasks.startAsyncTask function (IMPORTANT: DOT, NOT COLON), you want it to wrap the function started as an async task.

                   

                  PS - All Elare Plugin Framework calls are auto-wrapped with Debug.showErrors.

                   

                  So, you could write:

                  action = function( button )
                  
                       app:call( Call:new{ name=button.title, async=true, guard=App.guardVocal, main=function( call ) -- call as (async) task, and disallow recursive reentry - prompt user if he/she get's impatient (clicks button again before finished).
                  
                             local s, m = cat:update( 10, call.name, function( context, phase ) -- ten second timeout
                  
                                  if phase == 1 then
                  
                                      -- create keyword -- (paraphrased from SDK doc: The new keyword is not available for access until the with-do function returns).
                  
                                      return false -- continue to phase 2
                  
                                  elseif phase == 2 then
                  
                                      -- use created keyword
                  
                                      return true -- last phase (i.e. done). - note: same as returning nil (somewhat counter-conventionally).
                  
                                  end
                  
                             end )

                            if s then
                                 app:log( "Catalog updated." )
                            else
                                 app:error( "Unable to update catalog - ^1", m )
                            end

                        end, finale=function( call )         if call.status then             app:show{ info="No error." }         else             app:show{ warning="Error: ^1", call.message }         end      end } end,
                  • 6. Re: trouble with withWriteAccessDo
                    victorvodka Level 1

                    thanks for that, rob! with some fussing around i managed to get it to work! thanks so much!

                    the meat of code ended up looking like this:

                                                                           if phase == 1 then
                                                                                 
                                                                                -- create keyword -- (paraphrased from SDK doc: The new keyword is not available for access until the with-do function returns).
                                                                                
                                                                            
                                                                                local myKeyword = LrCatalog:createKeyword( 'XYZA: test', {}, true, nil  )
                                                                            
                                                                                return false -- continue to phase 2
                    
                                                                           elseif phase == 2 then
                                                                                -- use created keyword
                                                                                local photo = dialogData.photo
                                                                                if photo ~= nil then
                                                                                     --photo:addKeyword(myKeyword )
                                                                                end
                                                                                return true -- last phase (i.e. done). - note: same as returning nil (somewhat counter-conventionally).
                                                                           end
                    

                    i noticed that any error thrown in phase 1 or 2 caused the whole thing to fail, which is how this is supposed to work i guess. anyway, thanks again!  this was a really sticky problem!