We now handle the starting FileReadyToParse event

The problem was that when you start vim like "vim foo.cc", the FileReadyToParse
event is sent to the server before it's actually started up. Basically, a race
condition.

We _really_ don't want to miss that event. For C++ files, it tells the server to
start compiling the file.

So now PostDataToHandlerAsync in BaseRequest will retry the request 3 times
(with exponential backoff) before failing, thus giving the server time to boot.
This commit is contained in:
Strahinja Val Markovic 2013-10-02 17:09:25 -07:00
parent 9742302cbd
commit 7248979bb4
2 changed files with 41 additions and 15 deletions

View File

@ -20,10 +20,15 @@
import vim import vim
import json import json
import requests import requests
from retries import retries
from requests_futures.sessions import FuturesSession from requests_futures.sessions import FuturesSession
from concurrent.futures import ThreadPoolExecutor
from ycm import vimsupport from ycm import vimsupport
HEADERS = {'content-type': 'application/json'} HEADERS = {'content-type': 'application/json'}
# TODO: This TPE might be the reason we're shutting down slowly. It seems that
# it waits for all worker threads to stop before letting the interpreter exit.
EXECUTOR = ThreadPoolExecutor( max_workers = 4 )
class ServerError( Exception ): class ServerError( Exception ):
def __init__( self, message ): def __init__( self, message ):
@ -57,12 +62,24 @@ class BaseRequest( object ):
# This returns a future! Use JsonFromFuture to get the value. # This returns a future! Use JsonFromFuture to get the value.
@staticmethod @staticmethod
def PostDataToHandlerAsync( data, handler ): def PostDataToHandlerAsync( data, handler ):
def PostData( data, handler ):
return BaseRequest.session.post( _BuildUri( handler ), return BaseRequest.session.post( _BuildUri( handler ),
data = json.dumps( data ), data = json.dumps( data ),
headers = HEADERS ) headers = HEADERS )
@retries( 3, delay = 0.5 )
def DelayedPostData( data, handler ):
return requests.post( _BuildUri( handler ),
data = json.dumps( data ),
headers = HEADERS )
session = FuturesSession( max_workers = 4 ) if not _CheckServerIsHealthyWithCache():
return EXECUTOR.submit( DelayedPostData, data, handler )
return PostData( data, handler )
session = FuturesSession( executor = EXECUTOR )
server_location = 'http://localhost:6666' server_location = 'http://localhost:6666'
@ -102,3 +119,22 @@ def _BuildUri( handler ):
return ''.join( [ BaseRequest.server_location, '/', handler ] ) return ''.join( [ BaseRequest.server_location, '/', handler ] )
SERVER_HEALTHY = False
def _CheckServerIsHealthyWithCache():
global SERVER_HEALTHY
def _ServerIsHealthy():
response = requests.get( _BuildUri( 'healthy' ) )
response.raise_for_status()
return response.json()
if SERVER_HEALTHY:
return True
try:
SERVER_HEALTHY = _ServerIsHealthy()
return SERVER_HEALTHY
except:
return False

View File

@ -17,8 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import traceback
from ycm import vimsupport
from ycm.client.base_request import BaseRequest, BuildRequestData from ycm.client.base_request import BaseRequest, BuildRequestData
@ -35,15 +33,7 @@ class EventNotification( BaseRequest ):
request_data.update( self._extra_data ) request_data.update( self._extra_data )
request_data[ 'event_name' ] = self._event_name request_data[ 'event_name' ] = self._event_name
# On occasion, Vim tries to send event notifications to the server before
# it's up. This causes intrusive exception messages to interrupt the user.
# While we do want to log these exceptions just in case, we post them
# quietly to the Vim message log because nothing bad will happen if the
# server misses some events and we don't want to annoy the user.
try:
self.PostDataToHandlerAsync( request_data, 'event_notification' ) self.PostDataToHandlerAsync( request_data, 'event_notification' )
except:
vimsupport.EchoText( traceback.format_exc() )
def SendEventNotificationAsync( event_name, extra_data = None ): def SendEventNotificationAsync( event_name, extra_data = None ):