Forum Discussion

SteveK's avatar
SteveK
New Contributor III
12 days ago

Subtle bug in Example for Dynamic Dimensions

In the example code for the Dynamic Dimension Service there appears to be a subtle bug which will affect refresh of the dimensions.

ReadDynamicDimensionInfo(...) returns DateTime.Now:

' This api method will build the required object, straight from an SQL query.
Return api.ReadDynamicDimensionInfo(si, args, DateTime.Now, numSecondsBeforeCheckTS, _
    dbConn, sql.ToString, Nothing, Nothing, _
      "Name", "Description", "UniqueID", "Name", "Parent", "ParentID", "Parent", "AggWeight", True)

BUT ReadDynamicDimensionContentTimestamp sets the Timestamp as DateTime.UTCNow:

'Refresh once per minute (note: frequent refreshes such As one minute could degrade performance).
Dim utcNow As DateTime = DateTime.UtcNow
Return New DateTime(utcNow.Year, utcNow.Month, utcNow.Day, utcNow.Hour, utcNow.Minute, 0, 0, DateTimeKind.Utc)

This will matter if your refresh period is < 13(?) hours AND if your TimeZone is ahead of UTC......

It's an easy fix though!

Steve

8 Replies

  • JackLacava's avatar
    JackLacava
    Community Manager

    Well-spotted - we'll have a look. I would recommend using UTC everywhere for consistency.

    That sample is far from perfect - it also has a Using clause that is a bad idea, one should just use api.DbConnApp which is an already-open connection. Blame me ;)

  • rhankey's avatar
    rhankey
    Contributor II

    I don't think this is quiet the "bug" you think it is.

    Based on some testing, I have found that if you pass-in DateTime.UtcNow to DynamicDimensionInfo() or DynamicDataUnitData(), OS will trigger refreshes far sooner than you expect.  Using DateTime.UtcNow caused it to effectively ignore the 300 sec wait time I had configured.

    It would appear DynamicDimensionInfo() or DynamicDataUnitData() DO expect you to pass in DateTime.Now, as OS's code samples show,.  Presumably the functions must internally then convert the passed in Time to UTC time.

    That does seem a little inconsistent when ReadDynamicDimensionContentTimestamp() ReadDynamicDataUnitContentTimestamp() are both expected to return UTC time.  My personal sense is that DynamicDimensionInfo() or DynamicDataUnitData() should both be expecting UTCTime, or have an option to do so.

    • JackLacava's avatar
      JackLacava
      Community Manager

      I've not looked at the code, but tbh it shouldn't really matter - as long as you keep it consistent in all calls, you should get the expected behaviour. 

       So I would probably recommend using utcNow everywhere.

      • rhankey's avatar
        rhankey
        Contributor II

        Passing DateTime.UTCNow time into DynamicDimensionInfo() or DynamicDataUnitData() does not render expected results when in an EST time-zone when I set the refresh/expiry time at 300 seconds, whereas DateTime.Now does work correctly.  Presumably the app server must be converting the supplied time to UTC time, else there could be problems where users could be coming in from around the globe.

    • SteveK's avatar
      SteveK
      New Contributor III

      It could be that it assumes/sets DateTimeKind.Utc internally, just that it's not visible in the BR engine. I could see that it might appear to ignore your wait time depending upon which site of UTC you are on though

  • rhankey's avatar
    rhankey
    Contributor II

    While on a roll with DynamicDimensionService issues, here is another.

    All the Member functions in which you pass-in a DimTypeId fail when called from within a DynamicDimensionService file, if the DimTypeId matches that of the dynamic dimension currently being rebuilt.

    These functions all fail when they check the Dynamic Dim currently being (re)built, as I guess internally OS has not properly initialized the dimension until it receives the dynamic members and relationships you are about to (re)assign to the dimension.

    The workaround I've found is to use the variant of GetMemberInfo() that accepts a pass-in DimPk, so that you can pass-in the Inherited DimPk, and thus avoid having the OS Member function look at dynamic dimension you are in the process of (re)building.  The Member expansion functions all work, as they also require a DimPk rather than DimTypeId.

    • JackLacava's avatar
      JackLacava
      Community Manager

      Could you provide a sample? Because i've just tried with a simple GetMember and it works fine in 9.0. Likely it won't work if you're trying to look up a member of the dimension itself (because you've not finished building it, of course), but should work fine with other ones of the same dimension type.

      • rhankey's avatar
        rhankey
        Contributor II

        If my prior response was not clear, I apologize.  GetMemberId(), GetMemberName() etc that ask for DimTypeId work fine on other DimTypes, but fail if used to find a member on the DimType of the Dynamic Dimension being built.  The error message indicates it has issues with the Dyn Dim that is currently being built.  IMHO, these functions should be smart enough to skip over the dynamic dim that is in currently being rebuilt.  The use case is when you need to find MemberId's of specific inherited members to which you want to dynamic children.

        The workaround is to use the GetMemberInfo() variant that accepts DimPk, which if set to the InheritedDimPk then works.  All the other Member functions that take DimPk work fine.