1
1
import json
2
2
import time
3
+ import uuid
3
4
import logging
4
5
from urllib .parse import urlsplit
5
6
@@ -54,12 +55,33 @@ def release_expired_keys(self):
54
55
logger .warning ('expired keys are released, total: %s' , total )
55
56
56
57
58
+ class SimpleStoreManager (object ):
59
+ def __init__ (self ):
60
+ self ._store = {}
61
+
62
+ def create (self , obj ):
63
+ while True :
64
+ token = self ._new_token ()
65
+ if token in self ._store :
66
+ continue
67
+ self ._store [token ] = obj
68
+ return token
69
+
70
+ def pop (self , token ):
71
+ return self ._store .pop (token , None )
72
+
73
+ @staticmethod
74
+ def _new_token ():
75
+ return uuid .uuid4 ().hex
76
+
77
+
57
78
class SeleniumGridService (object ):
58
79
def __init__ (self , selenium_grid_client = None , lock_expired = 60 ):
59
80
self ._selenium_grid_client = selenium_grid_client or SeleniumGridClient ()
60
- self ._capabilities = []
81
+ self ._capabilities = [] # TODO: create a manager to handle capabilities
61
82
self ._appium_lock = SimpleLockManager (lock_expired ) # key: netloc
62
83
self ._udid_lock = SimpleLockManager (lock_expired ) # key: udid
84
+ self ._lock_store = SimpleStoreManager ()
63
85
64
86
def get_all_hubs_url (self ):
65
87
session = Session ()
@@ -86,16 +108,30 @@ def get_available_capabilities(self, platform_name,
86
108
result .append (cap )
87
109
return result
88
110
89
- def set_capabilities (self , caps ):
90
- self ._capabilities = caps
91
-
92
111
def update_capabilities (self , * _args ):
93
112
Observable .from_ (self .get_all_hubs_url (), scheduler = scheduler ) \
94
113
.distinct () \
95
114
.flat_map (self ._fetch_hub_detail ) \
96
115
.to_list () \
97
116
.subscribe (self .set_capabilities )
98
117
118
+ def lock_capability (self , appium_url , udid ):
119
+ appium_netloc = self ._get_netloc (appium_url )
120
+ self ._appium_lock .acquire (appium_netloc )
121
+ self ._udid_lock .acquire (udid )
122
+ return self ._lock_store .create ((appium_netloc , udid ))
123
+
124
+ def release_capability (self , lock_token ):
125
+ ret = self ._lock_store .pop (lock_token )
126
+ if ret is None :
127
+ return
128
+ appium_netloc , udid = ret
129
+ self ._appium_lock .release (appium_netloc )
130
+ self ._udid_lock .release (udid )
131
+
132
+ def set_capabilities (self , caps ):
133
+ self ._capabilities = caps
134
+
99
135
def update_capabilities_in_background (self , period = 10 ):
100
136
Observable .interval (period * 1000 , scheduler = scheduler ) \
101
137
.subscribe (self .update_capabilities )
@@ -123,10 +159,10 @@ def on_error(_e):
123
159
.flat_map (unpack_hub ) \
124
160
.catch_exception (handler = on_error ) # make sure this observable never emit error
125
161
126
-
127
- def _get_netloc (url ):
128
- (_ , netloc , * _ ) = urlsplit (url )
129
- return netloc
162
+ @ staticmethod
163
+ def _get_netloc (url ):
164
+ (_ , netloc , * _ ) = urlsplit (url )
165
+ return netloc
130
166
131
167
132
168
scheduler = IOLoopScheduler ()
0 commit comments