]> git.openstreetmap.org Git - rails.git/blobdiff - app/controllers/amf_controller.rb
Add a global timeout that is applied to most API requests.
[rails.git] / app / controllers / amf_controller.rb
index b6d8cbe539fee8325f91cc2863691381953569f0..f11700718556b95eec0b9f1a932dd027c64a43ed 100644 (file)
@@ -26,6 +26,7 @@
 # Any method that returns a status code (0 for ok) can also send:
 #      return(-1,"message")            <-- just puts up a dialogue
 #      return(-2,"message")            <-- also asks the user to e-mail me
+#   return(-3,'type',id)        <-- version conflict
 # 
 # To write to the Rails log, use logger.info("message").
 
@@ -42,6 +43,7 @@ class AmfController < ApplicationController
 
   session :off
   before_filter :check_api_writable
+  around_filter :api_call_timeout, :only => [:amf_read]
 
   # Main AMF handlers: process the raw AMF string (using AMF library) and
   # calls each action (private method) accordingly.
@@ -71,7 +73,7 @@ class AmfController < ApplicationController
         index=AMF.getstring(req)                       #  | get index in response sequence
         bytes=AMF.getlong(req)                         #  | get total size in bytes
         args=AMF.getvalue(req)                         #  | get response (probably an array)
-        logger.info("Executing AMF #{message}:#{index}")
+        logger.info("Executing AMF #{message}(#{args.join(',')}):#{index}")
 
         case message
           when 'getpresets';           results[index]=AMF.putdata(index,getpresets())
@@ -88,7 +90,7 @@ class AmfController < ApplicationController
           when 'getpoi';               results[index]=AMF.putdata(index,getpoi(*args))
         end
       end
-      logger.info("encoding AMF results")
+      logger.info("Encoding AMF results")
       sendresponse(results)
     else
       render :nothing => true, :status => :method_not_allowed
@@ -132,7 +134,7 @@ class AmfController < ApplicationController
           when 'startchangeset';               results[index]=AMF.putdata(index,startchangeset(*args))
         end
       end
-      logger.info("encoding AMF results")
+      logger.info("Encoding AMF results")
       sendresponse(results)
     else
       render :nothing => true, :status => :method_not_allowed
@@ -197,7 +199,7 @@ class AmfController < ApplicationController
     enlarge = [(xmax-xmin)/8,0.01].min
     xmin -= enlarge; ymin -= enlarge
     xmax += enlarge; ymax += enlarge
-    
+
     # check boundary is sane and area within defined
     # see /config/application.yml
     check_boundaries(xmin, ymin, xmax, ymax)
@@ -227,6 +229,8 @@ class AmfController < ApplicationController
 
     [0, ways, points, relations]
 
+  rescue OSM::APITimeoutError => err
+    [-1,"Sorry - I can't get the map for that area. The server said: #{err}"]
   rescue Exception => err
     [-2,"Sorry - I can't get the map for that area. The server said: #{err}"]
   end
@@ -505,12 +509,13 @@ class AmfController < ApplicationController
         new_relation.create_with_history(user)
       elsif visible
         # We're updating the relation
+        new_relation.id = relid
         relation.update_from(new_relation, user)
       else
         # We're deleting the relation
+        new_relation.id = relid
         relation.delete_with_history!(new_relation, user)
       end
-      updatetimeout(changeset_id)
     end # transaction
       
     if relid <= 0
@@ -521,9 +526,6 @@ class AmfController < ApplicationController
   rescue OSM::APIChangesetAlreadyClosedError => ex
     return [-1, "The changeset #{ex.changeset.id} was closed at #{ex.changeset.closed_at}."]
   rescue OSM::APIVersionMismatchError => ex
-    # Really need to check to see whether this is a server load issue, and the 
-    # last version was in the same changeset, or belongs to the same user, then
-    # we can return something different
     return [-3, "Sorry, someone else has changed this relation since you started editing. Please click the 'Edit' tab to reload the area. The server said: #{ex}"]
   rescue OSM::APIAlreadyDeletedError => ex
     return [-1, "The relation has already been deleted."]
@@ -595,6 +597,7 @@ class AmfController < ApplicationController
         else
           # We're updating an existing node
           previous=Node.find(id)
+          node.id=id
           previous.update_from(node, user)
           nodeversions[previous.id] = previous.version
         end
@@ -616,6 +619,7 @@ class AmfController < ApplicationController
       else
              way = Way.find(originalway)
                  if way.tags!=attributes or way.nds!=pointlist or !way.visible?
+                   new_way.id=originalway
            way.update_from(new_way, user)
         end
       end
@@ -627,6 +631,7 @@ class AmfController < ApplicationController
         new_node = Node.new
         new_node.changeset_id = changeset_id
         new_node.version = v.to_i
+        new_node.id = id.to_i
         begin
           node.delete_with_history!(new_node, user)
         rescue OSM::APIPreconditionFailedError => ex
@@ -634,7 +639,6 @@ class AmfController < ApplicationController
           # and we don't want to delete it
         end
       end
-      updatetimeout(changeset_id)
 
     end # transaction
 
@@ -642,9 +646,6 @@ class AmfController < ApplicationController
   rescue OSM::APIChangesetAlreadyClosedError => ex
     return [-2, "Sorry, your changeset #{ex.changeset.id} has been closed (at #{ex.changeset.closed_at})."]
   rescue OSM::APIVersionMismatchError => ex
-    # Really need to check to see whether this is a server load issue, and the 
-    # last version was in the same changeset, or belongs to the same user, then
-    # we can return something different
     return [-3, "Sorry, someone else has changed this way since you started editing. Click the 'Edit' tab to reload the area. The server said: #{ex}"]
   rescue OSM::APITooManyWayNodesError => ex
     return [-1, "You have tried to upload a really long way with #{ex.provided} points: only #{ex.max} are allowed."]
@@ -692,12 +693,13 @@ class AmfController < ApplicationController
         new_node.create_with_history(user)
       elsif visible
         # We're updating the node
+        new_node.id=id
         node.update_from(new_node, user)
       else
         # We're deleting the node
+        new_node.id=id
         node.delete_with_history!(new_node, user)
       end
-      updatetimeout(changeset_id)
 
     end # transaction
 
@@ -709,9 +711,6 @@ class AmfController < ApplicationController
   rescue OSM::APIChangesetAlreadyClosedError => ex
     return [-1, "The changeset #{ex.changeset.id} was closed at #{ex.changeset.closed_at}"]
   rescue OSM::APIVersionMismatchError => ex
-    # Really need to check to see whether this is a server load issue, and the 
-    # last version was in the same changeset, or belongs to the same user, then
-    # we can return something different
     return [-3, "Sorry, someone else has changed this point since you started editing. Please click the 'Edit' tab to reload the area. The server said: #{ex}"]
   rescue OSM::APIAlreadyDeletedError => ex
     return [-1, "The point has already been deleted"]
@@ -763,6 +762,7 @@ class AmfController < ApplicationController
       delete_way = Way.new
       delete_way.version = way_version
       delete_way.changeset_id = changeset_id
+      delete_way.id = way_id
       old_way.delete_with_history!(delete_way, user)
 
       # -- Delete unwanted nodes
@@ -772,6 +772,7 @@ class AmfController < ApplicationController
         new_node = Node.new
         new_node.changeset_id = changeset_id
         new_node.version = v.to_i
+        new_node.id = id.to_i
         begin
           node.delete_with_history!(new_node, user)
         rescue OSM::APIPreconditionFailedError => ex
@@ -779,7 +780,6 @@ class AmfController < ApplicationController
           # elsewhere and we don't want to delete it
         end
       end
-      updatetimeout(changeset_id)
 
     end # transaction
     [0, way_id]
@@ -815,15 +815,6 @@ class AmfController < ApplicationController
     return user
   end
 
-  # Update changeset timeout
-  # i.e. one hour after current edit
-  
-  def updatetimeout(changeset_id) #:doc:
-    cs = Changeset.find(changeset_id)
-    cs.closed_at = Time.now.getutc + Changeset::IDLE_TIMEOUT
-    cs.save!
-  end
-
   # Send AMF response
   
   def sendresponse(results)