Class and object dependencies, schedules
[plstackapi.git] / planetstack / observer / syncstep.py
1 import os
2 import base64
3 from planetstack.config import Config
4
5 class FailedDependency(Exception):
6         pass
7
8 class SyncStep:
9         """ A PlanetStack Sync step. 
10
11         Attributes:
12                 psmodel         Model name the step synchronizes 
13                 dependencies    list of names of models that must be synchronized first if the current model depends on them
14         """ 
15         slow=False
16         def get_prop(prop):
17                 try:
18                         sync_config_dir = Config().sync_config_dir
19                 except:
20                         sync_config_dir = '/etc/planetstack/sync'
21                 prop_config_path = '/'.join(sync_config_dir,self.name,prop)
22                 return open(prop_config_path).read().rstrip()
23
24         def __init__(self, **args):
25                 """Initialize a sync step
26                    Keyword arguments:
27                                 name -- Name of the step
28                                 provides -- PlanetStack models sync'd by this step
29                 """
30                 dependencies = []
31                 try:
32                         self.soft_deadline = int(self.get_prop('soft_deadline_seconds'))
33                 except:
34                         self.soft_deadline = 5 # 5 seconds
35
36                 return
37
38         def fetch_pending(self):
39                 return Sliver.objects.filter(ip=None)
40         
41         def check_dependencies(self, obj):
42                 for dep in dependencies:
43                         peer_object = getattr(obj, dep.name.lowercase())
44                         if (peer_object.pk==dep.pk):
45                                 raise DependencyFailed
46
47         def call(self, failed=failed_objects):
48                 pending = self.fetch_pending()
49                 failed = []
50                 for o in pending:
51                         if (not self.depends_on(o, failed)):
52                                 try:
53                                         check_dependencies(o) # Raises exception if failed                                      
54                                         self.sync_record(o)
55                                         o.enacted = datetime.now() # Is this the same timezone? XXX
56                                         o.save(update_fields=['enacted'])
57                                 except:
58                                         failed.append(o)
59                 return failed
60
61         def __call__(self):
62                 return self.call()