[asterisk-dev] Calendaring API
John Todd
jtodd at digium.com
Wed Oct 8 02:52:21 CDT 2008
To top-summarize:
I don't have any problem with the start/duration method you describe,
and I agree that it provides a more standard time parsing engine
method. I just tried to make it easier with my syntax, but I think
by trying to make it easier, it became more difficult. :-) Your
method makes more sense.
I was thinking a bit about the caching issue. Perhaps there is a way
to temporarily cache and refresh unnamed calendars automatically? In
the [general] section of calendars.conf, there might be something
like this:
[general]
;
; Do we cache un-named calendars that are referenced in the dialplan?
; This makes subsequent responses faster, which is important during
; call processing, and also lowers network lag for full calendar
; imports.
;
cacheunnamed=yes
;
; How long do we maintain state for an un-named calendar? (seconds)
; If the calendar is unused, and this timer expires, the calendar
; is "forgotten" until next requested. However, if the calendar is
; queried, the counter is reset to zero and starts again.
;
cacheduration=86400
;
; Un-named calendars are refreshed this often (seconds) for the duration
; that they live in the cache. This keeps them "useful" to subsequent
; queries without having to pause to re-load the entire calendar.
; If the calendar is unreachable on a refresh, the data is maintained
; until the cacheduration timer expires.
;
refresh=3600
;
JT
At 1:54 AM -0500 2008/10/8, Terry Wilson wrote:
>
>> [note to future archive surfers: this syntax does not exist; it is
>> currently
>> a figment of my imagination - please keep searching for what you
>> want, or
>> feel free to bring this thread back from the depths.]
>>
>>
>> core1*CLI> core show function CALENDAR_STATUS
>> -= Info about function 'CALENDAR_STATUS' =-
>>
>> [Syntax]
>> CALENDAR_STATUS(<calendar_name>,<value>[,<time range>][,<event-
>> number>])
>
>After a cursory glance I think I like the above format, but with some
>changes to the time range functionality. Perhaps:
>CALENDAR_STATUS(<calendar_name>,<value>[,<start-time>][,<duration>]
>[,<event-number>])
>
>> time range = a time range for the query, in the format of:
>>
>> YYYYMMDDHHMM["-<tzone-name>","-HH:MM"][&[YYYYMMDDHHMM["-<tzone-
>> name>","-HH:MM"]]
>>
>> Special name "now" can replace time and timezone.
>> Special indicators "+" and "-" can be used to add or
>> subtract minutes from a given time. If no timezone is
>> specified, Asterisk uses the timezone of the system as
>> set locally. Any references in timezone-names to numeric
>> hour/minute offsets are assumed to be from GMT, and any
>> use of "-" and "+" characters in the timezone names are
>> considered part of the timezone name and not as modifiers.
>> If time range is omitted, assumption is that the time
>> is "now".
>
>My initial inclination is to prefer the times just be in seconds since
>epoch. We already have the EPOCH variable, so we wouldn't need the
>"now" keyword. Then ranges from that are easily determined by adding
>seconds. Time zones and date conversions could be handled with the
>STRFTIME and STRPTIME dialplan functions. Since the dialplan already
>has these methods for handling time functions, it seems more Asterisk-
>y and interoperable to use them. Let me see if I can translate all of
>the examples...
>
>> examples:
>>
>> now+5
>> Looks up any events 5 minutes from this moment.
>
>${EPOCH}, 300
>
>> 200810061440
>> Looks up any events (using system timezone) that are
>> occuring on Oct 6, 2008 at 14:40.
>
>${STRPTIME(200810061440,,%Y%m%d%H%M%S)}
>
>> now&now+30
>> Looks up any events from this moment until one half
>> hour in the future.
>
>${EPOCH}, 1800
>
>> now-30&now+30
>> Looks up any events from half an hour ago to half
> > an hour in the future.
>
>$[${EPOCH} - 1800], 3600
>This and following queries involves a bit of calculation if using a
>duration field, so maybe having a start and end would be easier for
>it, but having to specify a start and endtime for querying just "right
>now" is kind of annoying. Right now I'm envisioning not providing a
>duration as "just intersecting the start time", and maybe if 0 or a
>negative number maybe being specified meaning an open end time--all
>events after start time (not that I'm sure that is a useful query).
>Otherwise we could do the start and end time and and have an empty
>start or end make the query open (+/- infinity) on that bound. So
>this query would be:
>$[${EPOCH} - 1800], $[${EPOCH} + 1800]
>
>> 200810061450&200810061550
>> Looks up any events for 2:50 PM until 3:50 PM, and uses
>> the
>> timezone of the local machine as the timezone modifier.
>
>${STRPTIME(20810061450,,%Y%m%d%H%M%S)}, 3600
>or
>${STRPTIME(20810061450,,%Y%m%d%H%M%S)}, ${STRPTIME(200810061550,,%Y%m%d
>%H%M%S)}
>> 200810061450-PDT&200810061550-PDT
>> Looks up any events for 2:50 PM Pacific Daylight Time
>> until 3:50 PM Pacific.
>
>${STRPTIME(200810061450,America/Los_Angeles,%Y%m%d%H%M%S)}, 3600
>or
>${STRPTIME(200810061450,America/Los_Angeles,%Y%m%d%H%M%S)}, $
>{STRPTIME(200810061550,America/Los_Angeles,%Y%m%d%H%M%S)}
>
>> 200810061450-08:00&200810061550-08:00
>> Looks up any events for October 6, 2008 2:50 PM Pacific
>> until October 6, 2008 3:50 PM Pacific, but doesn't
>> consider
>> daylight savings time - just uses 8 hour offset.
>
>${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M%S)}, 3600
>or
>${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M%S)},$
>{STRPTIME(200810061550,GMT-8,%Y%m%d%H%M%S)}
>
>> now-30&200810061450-08:00-120
>> Looks up any events from half an hour in the past until
>> two hours before October 6, 2008 2:50 Pacific
>> (otherwise known as 12:50 PM Pacific)
>
>$[${EPOCH} - 1800], $[1800 + ${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M
>%S)} - 7200 - ${EPOCH}]
>or
>$[${EPOCH} - 1800], $[${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M%S)} -
>7200]
>
>Now, I understand that most of those look relatively ugly, but there
>are several benefits: 1) We aren't inventing yet another way to
>represent datetimes and ranges in Asterisk. 2) With STRPTIME you can
>pass in the time in any format you choose and then work with epoch
>times that are easily manipulatable via simple arithmetic. 3) Using $
>{EPOCH} and offsets lets you completely ignore timezones and
>conversions. 4) The calendaring API internallhy does everything in
>GMT, so no more timezone processing has to be done inside the module.
>
>Most of the above is mostly academic, one is probably never going to
>do queries in the dialplan based on specific datetimes that aren't
>actually tied to some offset from "now". I agree with the sentiment
>of making queries flexible for people who might find a need for them
>(people are really good at using things in ways you don't anticipate),
>but implementing a new way to parse dates just inside the calendar
>module seems to me to be a lot of work for what amounts to a semantic
>difference which would need to be converted with STRPTIME anyway to be
>used with other time-related dialplan functions.
>
>> Examples:
>>
>> These examples use a calendar which has two (poorly scheduled)
>> events:
>> Oct 6, 2008 1:00 - 1:30 PM Pacific: "Get Lunch with Penny
>> Preddy"
>> Oct 6, 2008 1:15 - 1:45 PM Pacific: "Mrs. Johnson conference
>> call"
>> The calendar exists in calendar.conf as "calendar1".
>> The realtime clock at the moment of this example is 1:20 PM
>> Pacific, October 6 2008.
>>
>> ${CALENDAR_STATUS(calendar1,busystate)}
>> Returns "2", since there is at least one event at this moment.
>
>Assuming that 2 is the greatest value of busystate for the two events.
>
>> ${CALENDAR_STATUS(calendar1,getnum)}
>> Returns "2", since there are two events active at this moment.
>>
>> ${CALENDAR_STATUS(calendar1,summary)}
> > Returns "Get Lunch with Penny Preddy" as the first ordered result.
>> (see "Sorting Order..." in calendar.README)
>>
>> ${CALENDAR_STATUS(calendar1,summary,,2)}
>> Returns "Mrs. Johnson conference call"
>> (see "Sorting Order..." in calendar.README)
>>
>> ${CALENDAR_STATUS(calendar1,summary,now+20)}
>> Returns "Mrs. Johnson conference call" since at 1:40 we only
>> have that one
>> active event.
>
>${CALENDAR_STATUS(calendar1,summary,$[${EPOCH} + 1200])}
>
>> ${CALENDAR_STATUS(calendar1,summary,now+60&now+120)}
>> Returns a null string, since there are no entries on the calendar
>> that match that time span.
>
>${CALENDAR_STATUS(calendar1,summary,$[${EPOCH} + 3600],3600)}
>
>> ${CALENDAR_STATUS(calendar1,busystate,now+60&now+120)}
>> Returns a null string, since there are no entries on the calendar
>> that match that time span. Note that this is different than
>> replying with "0", which means there is an event but it is not
>> a "busy" event.
>
>${CALENDAR_STATUS(calendar1,busystate,$[${EPOCH} + 3600, 3600)}
>
>After going through this I think I might prefer the start/end time
>with leaving them empty for open ended queries instead of start and
>duration. Also, one problem is that if these queries are on an
>unnamed calendar, each query would most likely be pulling back the
>information for the calendar each time, which would really suck. It
>would be nice to come up with a way to query the range that you are
>going to be working with, then be able to access the data with
>successive calls w/o having to make separate http requests for each.
>With named calendars, we would just be querying data from within the
>timerange that is set in calendar.conf and is already cached.
>
>On a side note, unnamed calendars would not be accessible via the
>hints interface and each call that hit them in the dialplan would most
>likely result in a new http request. So users would need to be aware
>of how bad that would be on a busy system--from both a delay
>standpoint and a hammering your calendar server standpoint.
>
>> From a snippet of a hypothetical calendar.README file:
>>
>> SORTING ORDER MULTIPLE EVENTS
>>
>> If there are multiple events resulting from a query that is not a
>> time range and is a specific moment im time, the system will create
>> an ordered list, with the events being stacked by the nearest start
>> time to the given query time, nearest times to the query moment
>> ordered lowest in the list. If one or more events have the same
>> start time, then those events will be sub-ordered by nearest end
>> time, nearest times to the query moment ordered lowest in the list.
>> If one or more of those events have the same end time, then they will
>> be further sub-ordered by their UIDs, alphabetically/numerically,
>> with the highest ranking members appearing lowest in the resulting
>> list.
>>
>> If there are multiple events resulting from a query that consists of
>> a time start/end range, the system will create an ordered list.
>> Events that span or are equal to the starting edge of the query range
>> will be ordered by their start time, earliest start times lowest on
>> the list. If one or more are equal, then sort by duration, with
>> longer durations being lower on the list. If one or more of those
>> are equal, then sort alphabetically/numerically by UID, with highest
>> ranking members appearing lowest in the resulting list. The
>> remaining events are sorted by earliest start time, with earlier
>> start times being lower on the list. If one or more of these are the
>> same, then sort by duration, with longer durations being lower on the
>> list. If one or more of those are equal, then sort
>> alphabetically/numerically by UID, with highest ranking members
>> appearing lowest in the resulting list.
>>
>> For example, if a calendar event ("Management Retreat Meeting") spans
>> from 8:00A to 8:00P, and then another event ("Lunch") spans from
>> 12:00P to 1:00P, and yet another event ("Get a Soda") spans from
>> 12:00P to 12:05P, then a query about 12:03P would give an ordered
>> list of:
>> 1: Get a Soda
> > 2: Lunch
>> 3: Management Retreat Meeting
>>
>> and a query about 12:00P-1:00P time span would give an ordered list
>> of:
>> 1: Management Retreat Meeting
>> 2: Lunch
>> 3: Get a Soda
>>
>> Maximum number of stacked events is 255.
>>
>> If the query is a "busystate" query without a specific event-number
>> provided, and there is more than 1 concurrent event, then the highest
>> busystate of all of the events will be returned.
>
>After a cursory read of the ordering stuff, it seems reasonable.
>
>Terry
--
John Todd
jtodd at digium.com +1-256-428-6083
Asterisk Open Source Community Director
More information about the asterisk-dev
mailing list