I'm implementing a queue behavior for models that represent
asynchronous actions such as downloading images, manipulating images,
notifying client application of events and so on. Multiple hosts will
dequeue and actually run these tasks.
I have worked out how to add columns to facilitate dequeuing for
processing, how to add completion and failure hook methods to the
models and so on. I read that it is possible for a behavior to
generate additional tables (http://www.propelorm.org/wiki/ Documentation/1.5/Behaviors states that "Behaviors can modify their
table, and even add another table, by implementing the modifyTable
method"). One table would be for configuration (host1 should dequeue
at most 3 tasks at a time, host2 should dequeue 8 at a time. The
other table would serve as a task history for the queue item - host1,
3pm, 1st attempt, download failed - 404, host4, 4pm, 2nd attempt,
success.
I tried various methods of constructing table objects and adding them
to the same database as the table imbued with the behavior and have
accomplished nothing but errors. This lead me further and further up
the code base in attempt to determine how the generator actually adds
a table. Reading PropelOMTask::main() leads me to believe that
creating additional models using behaviors alone isn't actually
possible - not without rigging PropelOM::main() anyway.
PropelOM::main() contains a nested set of loops over models, databases
and finally tables eventually delegating to builder classes. Even if
I successfully constructed a table, adding it to the list of tables
currently getting traversed by main() on the fly would probably yield
unexpected results.
It seems that I would have to squeeze a custom builder into
configuration and have that builder in turn do the same thing a main()
iteration at table level would run. From what I have read so far this
could potentially require additional such builders to complete the
parallel hierarchy for multiple tasks tasks rooted in
AbstractPropelDataModelTask - many contain essentially the nested
loop, selecting different builders.
I figured I would ask the community in case I'm missing something
obvious/fundamental, or if my assumptions are correct, before heading
down the builder rabbit hole. In the time I have spent trying and
researching I could have cranked out separate configuration and
logging behaviors, declared the additional tables explicitly, and
linked them up via behavior configuration ... but I hate getting
stumped by stuff ...
Do you folks know of any examples that pull off creation of additional
tables using only behavior? Can anyone confirm custom builders would
get me there? Is this question something the developer list would be
annoyed by?
I haven't done any of that myself yet, but the versionable behavior
adds a table per model that implements that behavior.
Since Francois wrote that, it should be a good starting point for best
practices in that regard.
Daniel
On Mar 20, 3:27 am, Patrick Schweiger <pkschwei...@gmail.com> wrote:
> I'm implementing a queue behavior for models that represent
> asynchronous actions such as downloading images, manipulating images,
> notifying client application of events and so on. Multiple hosts will
> dequeue and actually run these tasks.
> I have worked out how to add columns to facilitate dequeuing for
> processing, how to add completion and failure hook methods to the
> models and so on. I read that it is possible for a behavior to
> generate additional tables (http://www.propelorm.org/wiki/ > Documentation/1.5/Behaviors states that "Behaviors can modify their
> table, and even add another table, by implementing the modifyTable
> method"). One table would be for configuration (host1 should dequeue
> at most 3 tasks at a time, host2 should dequeue 8 at a time. The
> other table would serve as a task history for the queue item - host1,
> 3pm, 1st attempt, download failed - 404, host4, 4pm, 2nd attempt,
> success.
> I tried various methods of constructing table objects and adding them
> to the same database as the table imbued with the behavior and have
> accomplished nothing but errors. This lead me further and further up
> the code base in attempt to determine how the generator actually adds
> a table. Reading PropelOMTask::main() leads me to believe that
> creating additional models using behaviors alone isn't actually
> possible - not without rigging PropelOM::main() anyway.
> PropelOM::main() contains a nested set of loops over models, databases
> and finally tables eventually delegating to builder classes. Even if
> I successfully constructed a table, adding it to the list of tables
> currently getting traversed by main() on the fly would probably yield
> unexpected results.
> It seems that I would have to squeeze a custom builder into
> configuration and have that builder in turn do the same thing a main()
> iteration at table level would run. From what I have read so far this
> could potentially require additional such builders to complete the
> parallel hierarchy for multiple tasks tasks rooted in
> AbstractPropelDataModelTask - many contain essentially the nested
> loop, selecting different builders.
> I figured I would ask the community in case I'm missing something
> obvious/fundamental, or if my assumptions are correct, before heading
> down the builder rabbit hole. In the time I have spent trying and
> researching I could have cranked out separate configuration and
> logging behaviors, declared the additional tables explicitly, and
> linked them up via behavior configuration ... but I hate getting
> stumped by stuff ...
> Do you folks know of any examples that pull off creation of additional
> tables using only behavior? Can anyone confirm custom builders would
> get me there? Is this question something the developer list would be
> annoyed by?
> I haven't done any of that myself yet, but the versionable behavior
> adds a table per model that implements that behavior.
> Since Francois wrote that, it should be a good starting point for best
> practices in that regard.
The 1.6 branch has seen a bunch of changes to model classes and it
took a little bit of fiddling around trying port versionable's logic
for adding a table to 1.5 behaviors. In particular the build was
failing to apply database behaviors to the newly created table despite
a loop that appears as if it should apply them just after the table is
created:
foreach ($database->getBehaviors() as $behavior) {
$behavior->modifyDatabase();
}
This loop actually appeared to be a no-op for the new table in the 1.5
generator state machine. When the build came around to processing the
newly created table, the timestampable database behavior was failing
to modifyTable() before running the preInsert(). Searching the 1.5
code base for all calls to modifyTable() turned up
Table::doFinalInitialization(). Calling doFinalInitialization() on
the newly created table did the trick for 1.5 builder state machine -
for reasons I didn't investigate when I discovered that this
doFinalInitialization() applies behaviors in 1.5 and does not in 1.6
(which must clearly be an improvement).
Hope this saves somebody trying to do this in 1.5 a bit of time.