Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Yusei Tahara
erp5
Commits
2d2c38f9
Commit
2d2c38f9
authored
Jun 28, 2013
by
Aurel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement better deletion mecanism & remove workflow transition overhead
parent
1b4cd9c7
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
323 additions
and
219 deletions
+323
-219
product/ERP5SyncML/Document/SyncMLSubscription.py
product/ERP5SyncML/Document/SyncMLSubscription.py
+276
-169
product/ERP5SyncML/Engine/AsynchronousEngine.py
product/ERP5SyncML/Engine/AsynchronousEngine.py
+15
-19
product/ERP5SyncML/Engine/EngineMixin.py
product/ERP5SyncML/Engine/EngineMixin.py
+7
-6
product/ERP5SyncML/Engine/SynchronousEngine.py
product/ERP5SyncML/Engine/SynchronousEngine.py
+9
-11
product/ERP5SyncML/Tool/SynchronizationTool.py
product/ERP5SyncML/Tool/SynchronizationTool.py
+9
-13
product/ERP5SyncML/tests/testERP5SyncML.py
product/ERP5SyncML/tests/testERP5SyncML.py
+7
-1
No files found.
product/ERP5SyncML/Document/SyncMLSubscription.py
View file @
2d2c38f9
This diff is collapsed.
Click to expand it.
product/ERP5SyncML/Engine/AsynchronousEngine.py
View file @
2d2c38f9
...
@@ -78,7 +78,10 @@ class SyncMLAsynchronousEngine(EngineMixin):
...
@@ -78,7 +78,10 @@ class SyncMLAsynchronousEngine(EngineMixin):
syncml_response
=
self
.
_generateBaseResponse
(
subscription
)
syncml_response
=
self
.
_generateBaseResponse
(
subscription
)
syncml_response
.
addFinal
()
syncml_response
.
addFinal
()
else
:
else
:
self
.
runGetAndActivate
(
subscription
=
subscription
,
tag
=
tag
)
# Make sure it is launched after indexation step
self
.
runGetAndActivate
(
subscription
=
subscription
,
tag
=
tag
,
after_method_id
=
(
"getAndIndex"
,
"SQLCatalog_indexSyncMLSignatureList"
))
syncml_logger
.
info
(
"X-> Client is sendind modification in activities"
)
syncml_logger
.
info
(
"X-> Client is sendind modification in activities"
)
# As we generated all activities to send data at once, process must not
# As we generated all activities to send data at once, process must not
# go back here, go into processing state thus status will be applied and
# go back here, go into processing state thus status will be applied and
...
@@ -163,10 +166,10 @@ class SyncMLAsynchronousEngine(EngineMixin):
...
@@ -163,10 +166,10 @@ class SyncMLAsynchronousEngine(EngineMixin):
# Apply command & send modifications
# Apply command & send modifications
# Apply status about object send & synchronized if any
# Apply status about object send & synchronized if any
s
ync_status_counter
=
s
elf
.
_readStatusList
(
syncml_request
,
subscriber
,
self
.
_readStatusList
(
syncml_request
,
subscriber
,
generate_alert
=
True
)
generate_alert
=
True
)
syncml_response
=
None
syncml_response
=
None
tag
=
subscri
ption_path
=
subscri
ber
.
getRelativeUrl
()
tag
=
subscriber
.
getRelativeUrl
()
after_method_id
=
None
after_method_id
=
None
if
subscriber
.
getSynchronizationState
()
==
"sending_modifications"
:
if
subscriber
.
getSynchronizationState
()
==
"sending_modifications"
:
if
syncml_request
.
isFinal
:
if
syncml_request
.
isFinal
:
...
@@ -202,15 +205,13 @@ class SyncMLAsynchronousEngine(EngineMixin):
...
@@ -202,15 +205,13 @@ class SyncMLAsynchronousEngine(EngineMixin):
if
syncml_request
.
isFinal
:
if
syncml_request
.
isFinal
:
# Server then sends its modifications
# Server then sends its modifications
subscriber
.
sendModifications
()
subscriber
.
sendModifications
()
# Now that everything is ok, init sync information
# Run indexation only once client have sent its modifications
if
subscriber
.
getSyncmlAlertCode
()
not
in
(
"one_way_from_client"
,
subscriber
.
indexSourceData
()
"refresh_from_client_only"
):
# Reset signature only if we have to check modifications on server side
subscriber
.
initialiseSynchronization
()
# Start to send modification only once we have processed
# Start to send modification only once we have processed
# all message from client
# all message from client
after_method_id
=
'processServerSynchronization'
,
after_method_id
=
(
'processServerSynchronization'
,
'SQLCatalog_indexSyncMLDocumentList'
)
# XXX after tag might also be required to make sure all data are indexed
tag
=
(
tag
,
"%s_reset"
%
subscriber
.
getPath
(),)
tag
=
(
tag
,
"%s_reset"
%
subscriber
.
getPath
(),)
# Do not continue in elif, as sending modifications is done in the same
# Do not continue in elif, as sending modifications is done in the same
# package as sending notifications
# package as sending notifications
...
@@ -242,10 +243,9 @@ class SyncMLAsynchronousEngine(EngineMixin):
...
@@ -242,10 +243,9 @@ class SyncMLAsynchronousEngine(EngineMixin):
after_tag
=
tag
).
sendMessage
(
after_tag
=
tag
).
sendMessage
(
xml
=
str
(
syncml_response
))
xml
=
str
(
syncml_response
))
def
runGetAndActivate
(
self
,
subscription
,
tag
,
after_method_id
=
None
):
def
runGetAndActivate
(
self
,
subscription
,
tag
,
after_method_id
=
None
):
"""
"""
Generate tag and method parameter and call the getAndActivate method
Launch the browsing of GID that will call the generation of syncml commands
"""
"""
activate_kw
=
{
activate_kw
=
{
'activity'
:
'SQLQueue'
,
'activity'
:
'SQLQueue'
,
...
@@ -253,20 +253,16 @@ class SyncMLAsynchronousEngine(EngineMixin):
...
@@ -253,20 +253,16 @@ class SyncMLAsynchronousEngine(EngineMixin):
'tag'
:
tag
,
'tag'
:
tag
,
'priority'
:
ACTIVITY_PRIORITY
'priority'
:
ACTIVITY_PRIORITY
}
}
method_kw
=
{
'subscription_path'
:
subscription
.
getRelativeUrl
(),
}
pref
=
getSite
().
portal_preferences
pref
=
getSite
().
portal_preferences
subscription
.
getAndActivate
(
subscription
.
getAndActivate
(
callback
=
"sendSyncCommand"
,
callback
=
"sendSyncCommand"
,
method_kw
=
method_kw
,
activate_kw
=
activate_kw
,
activate_kw
=
activate_kw
,
packet_size
=
pref
.
getPreferredDocumentRetrievedPerActivityCount
(),
packet_size
=
pref
.
getPreferredDocumentRetrievedPerActivityCount
(),
activity_count
=
pref
.
getPreferredRetrievalActivityCount
(),
activity_count
=
pref
.
getPreferredRetrievalActivityCount
(),
)
)
#
Then get deleted documen
t
#
then send the final message of this sync par
t
# this will send also the final message of this sync part
subscription
.
activate
(
after_tag
=
tag
,
subscription
.
activate
(
after_tag
=
tag
).
_getDeletedData
()
priority
=
ACTIVITY_PRIORITY
+
1
).
_sendFinalMessage
()
return
True
return
True
...
...
product/ERP5SyncML/Engine/EngineMixin.py
View file @
2d2c38f9
...
@@ -145,9 +145,10 @@ class EngineMixin(object):
...
@@ -145,9 +145,10 @@ class EngineMixin(object):
signature
=
domain
.
getSignatureFromGid
(
object_gid
)
signature
=
domain
.
getSignatureFromGid
(
object_gid
)
if
status
[
'status_code'
]
==
resolveSyncmlStatusCode
(
'success'
):
if
status
[
'status_code'
]
==
resolveSyncmlStatusCode
(
'success'
):
if
signature
:
if
signature
:
domain
.
z_delete_data_from_path
(
path
=
signature
.
getPath
())
domain
.
_delObject
(
signature
.
getId
())
domain
.
_delObject
(
signature
.
getId
())
else
:
else
:
raise
ValueError
(
"Found no signature to delete
"
)
raise
ValueError
(
"Found no signature to delete
for gid %s"
%
(
object_gid
,)
)
else
:
else
:
raise
ValueError
(
"Unknown status code : %r"
%
(
status
[
'status_code'
],))
raise
ValueError
(
"Unknown status code : %r"
%
(
status
[
'status_code'
],))
syncml_logger
.
error
(
"
\
t
Object deleted %s"
%
syncml_logger
.
error
(
"
\
t
Object deleted %s"
%
...
@@ -191,10 +192,8 @@ class EngineMixin(object):
...
@@ -191,10 +192,8 @@ class EngineMixin(object):
if
subscription
.
getAuthenticationState
()
!=
'logged_in'
:
if
subscription
.
getAuthenticationState
()
!=
'logged_in'
:
# Workflow action
# Workflow action
subscription
.
login
()
subscription
.
login
()
if
subscription
.
getSyncmlAlertCode
()
not
in
(
"one_way_from_server"
,
"refresh_from_server_only"
):
subscription
.
indexSourceData
(
client
=
True
)
# Reset signature only if client send its modification to server
subscription
.
initialiseSynchronization
()
# Create the package 1
# Create the package 1
syncml_response
=
SyncMLResponse
()
syncml_response
=
SyncMLResponse
()
...
@@ -301,7 +300,9 @@ class EngineMixin(object):
...
@@ -301,7 +300,9 @@ class EngineMixin(object):
'one_way_from_server'
,
'one_way_from_server'
,
'refresh_from_client_only'
,
'refresh_from_client_only'
,
'one_way_from_client'
):
'one_way_from_client'
):
# XXX Why re-editing here ?
# Make sure we update configuration based on publication data
# so that manual edition is propagated
# XXX Must check all properties that must be setted
subscriber
.
setXmlBindingGeneratorMethodId
(
subscriber
.
setXmlBindingGeneratorMethodId
(
publication
.
getXmlBindingGeneratorMethodId
())
publication
.
getXmlBindingGeneratorMethodId
())
subscriber
.
setConduitModuleId
(
publication
.
getConduitModuleId
())
subscriber
.
setConduitModuleId
(
publication
.
getConduitModuleId
())
...
...
product/ERP5SyncML/Engine/SynchronousEngine.py
View file @
2d2c38f9
...
@@ -29,6 +29,7 @@ from logging import getLogger
...
@@ -29,6 +29,7 @@ from logging import getLogger
from
Products.ERP5SyncML.Engine.EngineMixin
import
EngineMixin
from
Products.ERP5SyncML.Engine.EngineMixin
import
EngineMixin
from
Products.ERP5SyncML.SyncMLConstant
import
SynchronizationError
from
Products.ERP5SyncML.SyncMLConstant
import
SynchronizationError
from
Products.ERP5.ERP5Site
import
getSite
syncml_logger
=
getLogger
(
'ERP5SyncML'
)
syncml_logger
=
getLogger
(
'ERP5SyncML'
)
...
@@ -81,13 +82,12 @@ class SyncMLSynchronousEngine(EngineMixin):
...
@@ -81,13 +82,12 @@ class SyncMLSynchronousEngine(EngineMixin):
# We only get data from server
# We only get data from server
finished
=
True
finished
=
True
else
:
else
:
finished
=
subscription
.
_getSyncMLData
(
finished
=
subscription
.
_getSyncMLData
(
syncml_response
=
syncml_response
,
syncml_response
=
syncml_response
,
min_gid
=
None
,
max_gid
=
None
)
)
syncml_logger
.
info
(
"-> Client sendind modification, finished %s"
%
(
finished
,))
syncml_logger
.
info
(
"-> Client sendind modification, finished %s"
%
(
finished
,))
if
finished
:
if
finished
:
# Add deleted objets
# Add deleted objets
subscription
.
_getDeletedData
(
syncml_response
=
syncml_response
)
#
subscription._getDeletedData(syncml_response=syncml_response)
# Notify that all modifications were sent
# Notify that all modifications were sent
syncml_response
.
addFinal
()
syncml_response
.
addFinal
()
# Will then start processing sync commands from server
# Will then start processing sync commands from server
...
@@ -191,10 +191,8 @@ class SyncMLSynchronousEngine(EngineMixin):
...
@@ -191,10 +191,8 @@ class SyncMLSynchronousEngine(EngineMixin):
if
syncml_request
.
isFinal
:
if
syncml_request
.
isFinal
:
# Server will now send its modifications
# Server will now send its modifications
subscriber
.
sendModifications
()
subscriber
.
sendModifications
()
if
subscriber
.
getSyncmlAlertCode
()
not
in
(
"one_way_from_client"
,
# Run indexation only once client has sent its modifications
"refresh_from_client_only"
):
subscriber
.
indexSourceData
()
# Reset signature only if we have to check modifications on server side
subscriber
.
initialiseSynchronization
()
# Do not continue in elif, as sending modifications is done in the same
# Do not continue in elif, as sending modifications is done in the same
# package as sending notifications
# package as sending notifications
...
@@ -205,11 +203,11 @@ class SyncMLSynchronousEngine(EngineMixin):
...
@@ -205,11 +203,11 @@ class SyncMLSynchronousEngine(EngineMixin):
# We only get data from client
# We only get data from client
finished
=
True
finished
=
True
else
:
else
:
finished
=
subscriber
.
_getSyncMLData
(
finished
=
subscriber
.
_getSyncMLData
(
syncml_response
=
syncml_response
,
syncml_response
=
syncml_respons
e
)
min_gid
=
None
,
max_gid
=
Non
e
)
syncml_logger
.
info
(
"-> Server sendind data, finished %s"
%
(
finished
,))
syncml_logger
.
info
(
"-> Server sendind data, finished %s"
%
(
finished
,))
if
finished
:
if
finished
:
subscriber
.
_getDeletedData
(
syncml_response
=
syncml_response
)
#
subscriber._getDeletedData(syncml_response=syncml_response)
syncml_response
.
addFinal
()
syncml_response
.
addFinal
()
subscriber
.
waitNotifications
()
subscriber
.
waitNotifications
()
# Do not go into finished here as we must wait for
# Do not go into finished here as we must wait for
...
...
product/ERP5SyncML/Tool/SynchronizationTool.py
View file @
2d2c38f9
...
@@ -399,13 +399,14 @@ class SynchronizationTool(BaseTool):
...
@@ -399,13 +399,14 @@ class SynchronizationTool(BaseTool):
return
str
(
syncml_response
)
return
str
(
syncml_response
)
# As engines are not zodb objects, the tool acts as a placeholder for methods
# that need to be called in activities
def
applySyncCommand
(
self
,
subscription_path
,
response_message_id
,
def
applySyncCommand
(
self
,
subscription_path
,
response_message_id
,
activate_kw
,
**
kw
):
activate_kw
,
**
kw
):
"""
"""
This methods is intented to be called by asynchronous engine in activity to
This methods is intented to be called by asynchronous engine in activity to
apply sync commands for a subset of data
apply sync commands for a subset of data
As engines are not zodb object, the tool acts as a placeholder for method
that need to be called in activities
"""
"""
subscription
=
self
.
restrictedTraverse
(
subscription_path
)
subscription
=
self
.
restrictedTraverse
(
subscription_path
)
assert
subscription
is
not
None
,
"Impossible to find subscription %s"
\
assert
subscription
is
not
None
,
"Impossible to find subscription %s"
\
...
@@ -437,13 +438,11 @@ class SynchronizationTool(BaseTool):
...
@@ -437,13 +438,11 @@ class SynchronizationTool(BaseTool):
def
sendSyncCommand
(
self
,
id_list
,
message_id
,
subscription_path
,
def
sendSyncCommand
(
self
,
g
id_list
,
message_id
,
subscription_path
,
activate_kw
,
is_final_message
=
False
):
activate_kw
,
first_call
=
False
,
last_call
=
False
):
"""
"""
This methods is intented to be called by asynchronous engine in activity to
This methods is intented to be called by asynchronous engine in activity to
send sync commands for a subset of data
send sync commands for a subset of data
As engines are not zodb object, the tool acts as a placeholder for method
that need to be called in activities
"""
"""
subscription
=
self
.
restrictedTraverse
(
subscription_path
)
subscription
=
self
.
restrictedTraverse
(
subscription_path
)
assert
subscription
is
not
None
,
"Impossible to find subscription %s"
\
assert
subscription
is
not
None
,
"Impossible to find subscription %s"
\
...
@@ -457,17 +456,14 @@ class SynchronizationTool(BaseTool):
...
@@ -457,17 +456,14 @@ class SynchronizationTool(BaseTool):
source
=
subscription
.
getSubscriptionUrlString
())
source
=
subscription
.
getSubscriptionUrlString
())
syncml_response
.
addBody
()
syncml_response
.
addBody
()
subscription
.
_getSyncMLData
(
subscription
.
_getSyncMLData
(
syncml_response
=
syncml_response
,
syncml_response
=
syncml_response
,
id_list
=
id_list
,
gid_list
=
gid_list
,
first_call
=
first_call
,
last_call
=
last_call
,
)
)
if
is_final_message
:
# Send the message in activity to prevent recomputation of data in case of
# Notify that all modifications were sent
syncml_response
.
addFinal
()
# Send the message in activity to prevent recomputing data in case of
# transport failure
# transport failure
# activate_kw["group_method_id"] = None
# activate_kw["group_method_id"] = None
# activate_kw["group_method_cost"] = .05
# activate_kw["group_method_cost"] = .05
...
...
product/ERP5SyncML/tests/testERP5SyncML.py
View file @
2d2c38f9
...
@@ -44,6 +44,7 @@ from Products.ERP5SyncML.Document import SyncMLSubscription
...
@@ -44,6 +44,7 @@ from Products.ERP5SyncML.Document import SyncMLSubscription
from
Products.ERP5SyncML.tests.testERP5SyncMLMixin
import
TestERP5SyncMLMixin
\
from
Products.ERP5SyncML.tests.testERP5SyncMLMixin
import
TestERP5SyncMLMixin
\
as
TestMixin
as
TestMixin
from
Products.ERP5Type.tests.backportUnittest
import
expectedFailure
from
Products.ERP5Type.tests.backportUnittest
import
expectedFailure
from
_mysql_exceptions
import
OperationalError
class
TestERP5SyncMLMixin
(
TestMixin
):
class
TestERP5SyncMLMixin
(
TestMixin
):
...
@@ -98,6 +99,8 @@ class TestERP5SyncMLMixin(TestMixin):
...
@@ -98,6 +99,8 @@ class TestERP5SyncMLMixin(TestMixin):
def
afterSetUp
(
self
):
def
afterSetUp
(
self
):
"""Setup."""
"""Setup."""
self
.
login
()
self
.
login
()
self
.
portal
.
z_drop_syncml
()
self
.
portal
.
z_create_syncml
()
# This test creates Person inside Person, so we modifiy type information to
# This test creates Person inside Person, so we modifiy type information to
# allow anything inside Person (we'll cleanup on teardown)
# allow anything inside Person (we'll cleanup on teardown)
self
.
getTypesTool
().
getTypeInfo
(
'Person'
).
filter_content_types
=
0
self
.
getTypesTool
().
getTypeInfo
(
'Person'
).
filter_content_types
=
0
...
@@ -228,6 +231,7 @@ class TestERP5SyncMLMixin(TestMixin):
...
@@ -228,6 +231,7 @@ class TestERP5SyncMLMixin(TestMixin):
result
=
portal_sync
.
processClientSynchronization
(
subscription
.
getPath
())
result
=
portal_sync
.
processClientSynchronization
(
subscription
.
getPath
())
self
.
tic
()
self
.
tic
()
nb_message
+=
1
nb_message
+=
1
self
.
tic
()
return
nb_message
return
nb_message
def
synchronizeWithBrokenMessage
(
self
,
id
):
def
synchronizeWithBrokenMessage
(
self
,
id
):
...
@@ -948,6 +952,8 @@ return [context[%r]]
...
@@ -948,6 +952,8 @@ return [context[%r]]
person_server
.
manage_delObjects
(
self
.
id1
)
person_server
.
manage_delObjects
(
self
.
id1
)
person_client1
=
self
.
getPersonClient1
()
person_client1
=
self
.
getPersonClient1
()
person_client1
.
manage_delObjects
(
self
.
id2
)
person_client1
.
manage_delObjects
(
self
.
id2
)
# import ipdb
# ipdb.set_trace()
self
.
synchronize
(
self
.
sub_id1
)
self
.
synchronize
(
self
.
sub_id1
)
self
.
synchronize
(
self
.
sub_id2
)
self
.
synchronize
(
self
.
sub_id2
)
self
.
checkSynchronizationStateIsSynchronized
()
self
.
checkSynchronizationStateIsSynchronized
()
...
@@ -1543,7 +1549,7 @@ return [context[%r]]
...
@@ -1543,7 +1549,7 @@ return [context[%r]]
self
.
assertEquals
(
client_person
.
getLastName
(),
self
.
last_name1
)
self
.
assertEquals
(
client_person
.
getLastName
(),
self
.
last_name1
)
# reset for refresh sync
# reset for refresh sync
# after synchroniz
e, the client object retrieve value of
server
# after synchroniz
ation, the client retrieves value from
server
self
.
resetSignaturePublicationAndSubscription
()
self
.
resetSignaturePublicationAndSubscription
()
self
.
synchronize
(
self
.
sub_id1
)
self
.
synchronize
(
self
.
sub_id1
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment