-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clean up a bunch of stuff inside of Axon #426
Conversation
vEpiphyte
commented
Sep 7, 2017
•
edited
Loading
edited
- Add various docstrings
- Make Axon configable
- Make AxonHost configable
- Add tracking to the axonhost the space used in a host
- Update unit tests for Axons to account for configable options.
- UnitTests for Axons were broken into four classes (for sanity) - AxonTest for testing the base Axon, AxonFSTest for testing the FS features, AxonHostTest for testing the AxonHost class, and AxonClusterTest for testing the AxonCluster class.
- Fixed a bug in the daemon.py Onhelp() class which could cause a runtimewarning due to dictionary size changing.
- Update SvcProxy.getSynSvcs to return a list instead of a dict_values
- Randomize the axon's allocated too by calls to AxonCluster.alloc()
- Add a test spinning up a svcbus and axonhost, tearing them down and spinning them back up.
- Ensure the clone axon does not have any clones of its own.
- If an axon is a clone, it doesn't need to find clones or fire other clones
- Make Heap's reactor resize actually resize the underlying atom file.
- Initialize the svcproxy local attributes prior to strapping in the event handlers. This prevents events firing during init before class attributes are set.
- Have the axonhost advertise itself on the bus AFTER it has made or instantiated any local axons it needs to do. This allows axons to then find hosts on the bus after the axonhosts have finished doing their startup and then they can start doing clone operations.
- Address a issue in the Axon datamodel where clone :host was not present
- hashset's hashes are now immutable (tuple)
- logging in tests is now run by envars and has useful messages format
- make sure we check the guid in the axoncluster test.
- Enable caching on the Axon cortices. This required updating some of the Axon FS APIs to not perform row-level operations.
- Rewrite Cortex formTufoByTufo docstring, add formTufoByTufo test.
- Add a Cortex test for delTufoProp with caching.
- Misc test coverage improvements
- Remove Axon.syncs() api. It is not compatible with delivering one sync event at a time from the persistence file, which requires updating the persistence file for each event sent.
- Add a skipLongTests helper to the SynTest class to enable skipping tests which may run long. Run those only when SYN_RUN_LONG_TESTS envar is set.
- Add -rs switch to print skip messages in pytest.
6090827
to
2546fb3
Compare
fc47a42
to
73bcfe3
Compare
07cac3e
to
fecac52
Compare
@@ -96,6 +96,7 @@ def _actSyncHeapWrite(self, mesg): | |||
|
|||
def _actSyncHeapResize(self, mesg): | |||
size = mesg[1].get('size') | |||
self.atom.resize(size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
e3f7955
to
38ee54d
Compare
d9d7ccf
to
3231ab1
Compare
synapse/axon.py
Outdated
@@ -32,36 +34,34 @@ | |||
|
|||
_fs_attrs = ('st_mode', 'st_nlink', 'st_size', 'st_atime', 'st_ctime', 'st_mtime') | |||
|
|||
class AxonHost(s_eventbus.EventBus): | |||
logging.basicConfig(level=logging.DEBUG, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nuke
synapse/axon.py
Outdated
'doc': 'Max total allocations for Axons created by the host. ' | ||
'Only applies if set to a positive integer.'}), | ||
('axonhost:syncmax', {'type': 'int', 'defval': gigabyte * 10, | ||
'doc': ''}), # XXX Words |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
undefined option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch
synapse/axon.py
Outdated
) | ||
return confdefs | ||
|
||
@s_eventbus.on('syn:conf:set') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decorator to nuke
@s_common.firethread | ||
def _fireAxonClones(self): | ||
|
||
# If this axon is a clone, then don't try to make or find other clones |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is enforcing the idea that a clone can't have a clone.
synapse/axon.py
Outdated
except Exception as e: | ||
logger.exception('findAxonClones') | ||
logger.exception('Unhandled exception during _findAxonClones') | ||
|
||
def _findAxonClone(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function gives preference to host's with the lowest # of axons. We still have a issue where, in a given set of axon hosts in a bus during startup; multiple hosts may slam the first host with a low count at first.
synapse/axon.py
Outdated
''' | ||
if htype == 'guid': | ||
blob = self.core.getTufoByProp('axon:blob', valu=hvalu) | ||
else: | ||
blob = self.core.getTufoByProp('axon:blob:%s' % htype, valu=hvalu) | ||
return self.iterblob(blob) | ||
if blob: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous behavior returned a generator; while the docs said it yielded bytes. This makes the behavior more explicit.
@@ -124,6 +124,14 @@ class SvcProxy(s_eventbus.EventBus): | |||
def __init__(self, sbus, timeout=None): | |||
s_eventbus.EventBus.__init__(self) | |||
|
|||
self.byiden = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these had to be moved otherwise the service callbacks could fire prior to the service proxy having items to accessing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good call!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
synapse/tests/test_axon.py
Outdated
self.eq(axonbyts, cv) | ||
|
||
# Wait for clones to react to the events from axon0 | ||
time.sleep(2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we replace this time.sleep with something else?
Codecov Report
@@ Coverage Diff @@
## master #426 +/- ##
==========================================
+ Coverage 90.7% 90.99% +0.28%
==========================================
Files 123 123
Lines 14109 14166 +57
==========================================
+ Hits 12798 12890 +92
+ Misses 1311 1276 -35
Continue to review full report at Codecov.
|
d1d4de6
to
ac398bc
Compare
synapse/axon.py
Outdated
@@ -473,7 +534,7 @@ def __init__(self, axondir, **opts): | |||
self.axthrs = set() | |||
|
|||
self.setAxonInfo('link', self.link) | |||
self.setAxonInfo('opts', self.opts) | |||
self.setAxonInfo('opts', {key: self.getConfOpt(key) for key, _ in self.getConfDefs().items()}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could/would/should probably utilitize this dict comprehension so we can reuse it. perhaps something like getConfOpts() returning a dict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
synapse/axon.py
Outdated
fd.write(byts) | ||
|
||
Returns: | ||
bytes: A chunk of bytes | ||
''' | ||
if htype == 'guid': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should just add axon:blob:guid as a convenience secondary prop to eliminate this if/else logic
(i know it's not part of these changes :) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is cheap to tweak and test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
per discussion, we're not going to do this.
synapse/axon.py
Outdated
if blob: | ||
for byts in self.iterblob(blob): | ||
yield byts | ||
# XXX should throw an exception here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably should, yea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
synapse/axon.py
Outdated
|
||
for byts in axon.iterAxonBlob(blob): | ||
dostuff(byts) | ||
byts = b''.join((_byts for _bytes in eaxon.iterAxonBlob(blob))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_byts vs _bytes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vEpiphyte @invisig0th - Does this still need to be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
synapse/axon.py
Outdated
|
||
for byts in axon.iterAxonBlob(blob): | ||
dostuff(byts) | ||
byts = b''.join((_byts for _bytes in eaxon.iterAxonBlob(blob))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, it's probably a bad precedent to encourage them to concat bytes together from an iterative API like this, since the design is meant to handle multi-gig files. Maybe an example more like
fd = file('foo.bin','wb')
for byts in axon.iterAxonBlob(blob):
fd.write(byts)
or some such...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vEpiphyte @invisig0th - Does this still need to be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed. (example clarified)
synapse/axon.py
Outdated
# we're passing the latest axonbus to the Axon so it can register | ||
# itself properly. | ||
if 'axon:axonbus' in opts: | ||
axonbus = opts.get('axon:axonbus') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This construct causes 2 hash calculations and tree lookups. Most of the rest of the code base does this like so:
axonbus = opts.get('axonbus')
if axonbus is not None:
dostuff()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
synapse/axon.py
Outdated
dict: Configable dict of valid options which can be passed to a Axon() | ||
''' | ||
ret = {} | ||
for name, _ in self.getConfDefs().items(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could avoid this if we made the axonhost config options that were specifically for individual axons start with just axon: and get passed through. They are essentially the "axon options known by axonhost" so it seems clean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now cleaner but we still have to do some examination of the options since we can't just transparently pass options down to the axon.
synapse/axon.py
Outdated
'doc': 'Max total allocations for Axons created by the host. ' | ||
'Only applies if set to a positive integer.'}), | ||
('axonhost:syncmax', {'type': 'int', 'defval': gigabyte * 10, | ||
'doc': ''}), # XXX Words |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch
@@ -124,6 +124,14 @@ class SvcProxy(s_eventbus.EventBus): | |||
def __init__(self, sbus, timeout=None): | |||
s_eventbus.EventBus.__init__(self) | |||
|
|||
self.byiden = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good call!
synapse/tests/common.py
Outdated
@@ -81,6 +84,10 @@ def skipIfNoInternet(self): | |||
if os.getenv('SYN_TEST_NO_INTERNET'): | |||
raise unittest.SkipTest('no internet access') | |||
|
|||
def skipLongTests(self): | |||
if not os.getenv('SYN_RUN_LONG_TESTS'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like it should default the other way? I'd rather a "check it out and run" tries to run everything, and we tweak them "off" when it's not right for the use case. Probably most intuitive to rename it to "SYN_TEST_SKIP_LONG" or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like every test to run by default and have these test skip env vars all be SYN_SKIP_...
like the "skip if no internet" fn in your other PR. I do like having a way to skip long tests though. We could have push builds skip them, but PR builds run them to free up some build server time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This have been renamed to SYN_TEST_SKIP_LONG
to explicitly skip long running tests. The .drone.yml was updated to set this envar to 1 on PUSH
events.
@@ -124,6 +124,14 @@ class SvcProxy(s_eventbus.EventBus): | |||
def __init__(self, sbus, timeout=None): | |||
s_eventbus.EventBus.__init__(self) | |||
|
|||
self.byiden = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
synapse/tests/common.py
Outdated
@@ -81,6 +84,10 @@ def skipIfNoInternet(self): | |||
if os.getenv('SYN_TEST_NO_INTERNET'): | |||
raise unittest.SkipTest('no internet access') | |||
|
|||
def skipLongTests(self): | |||
if not os.getenv('SYN_RUN_LONG_TESTS'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like every test to run by default and have these test skip env vars all be SYN_SKIP_...
like the "skip if no internet" fn in your other PR. I do like having a way to skip long tests though. We could have push builds skip them, but PR builds run them to free up some build server time.
synapse/axon.py
Outdated
self.axonbus.runSynSvc(s_common.guid(), self) | ||
# track the total number of bytes which may be used by axons | ||
# associated with this axonhost (disregarding heap overhead) | ||
self.usedspace = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be tracking heap overhead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think this is a old comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clarified comment
synapse/tests/test_axon.py
Outdated
axon = s_axon.Axon(axondir, syncsize=64) | ||
# XXX It is not clear what this test is actually testing since syncsize is not used by anything inside of | ||
# axon.py | ||
axon = s_axon.Axon(axondir, **{'axon:syncsize': 64}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should syncsize be removed then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could probably rip it out
43dc8d7
to
3d77567
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed again and added two comments. 👍 from me after they're resolved.
- Add various docstrings - Make Axon configable - Make AxonHost configable - Add tracking to the axon to track the space used in one / the space used in a axonhost - Update unit tests for Axons - Add axonhost:clones to set a default number of clones for a child axon - Update SvcProxy.getSynSvcs to return a list instead of a dict_values - Randomize the axon's allocated too by calls to AxonCluster.alloc() - Add a test spining up a svcbus and axonhost, tearing them down and spinning them back up. - The clone axon does not have any clones of its own. - If an axon is a clone, it doens't need to find clones or fire other clones - Make Heap's reactor resize actually resize the underlying atom file. - Initialize the svcproxy local attributes prior to strapping in the event handlers. - Have the axonhost advertise itself on the bus AFTER it has made or instantiated any local axons it needs to do. This allows axons to then find hosts on the bus after the axonhosts have finished doing their startup and then they can start doing clone operations. - Address a issue in the Axon datamodel where clone :host was not present - hashset's hashes are now immutable (tuple) - logging in tests is now run by envars and has useful messages format - make sure we check the guid in the axoncluster test. - Enable caching on the Axon cortices. This required updating some of the Axon FS APIs to not perform row-level operations. - Rewrite Cortex formTufoByTufo docstring, add formTufoByTufo test. - Add a Cortex test for delTufoProp with caching. - Misc test coverage improvements - Remove Axon.syncs() api. It is not compatible with delivering one sync event at a time from the persistence file, which requires updating the persistence file for each event sent. - Add a skipLongTests helper to the SynTest class to enable skipping tests which may run long. Run those only when SYN_RUN_LONG_TESTS envar is set. - Add -rs switch to print skip messages in pytest.
…eve, in one pass, all of the configable options and their values for an object.
…o a positive integer before skiping tests. Update .drone.yml to skip long tests on push events.
…he axon: namespace.