| 815 | self.dbapi_connection = None |
| 816 | |
| 817 | def get_connection(self) -> DBAPIConnection: |
| 818 | recycle = False |
| 819 | |
| 820 | # NOTE: the various comparisons here are assuming that measurable time |
| 821 | # passes between these state changes. however, time.time() is not |
| 822 | # guaranteed to have sub-second precision. comparisons of |
| 823 | # "invalidation time" to "starttime" should perhaps use >= so that the |
| 824 | # state change can take place assuming no measurable time has passed, |
| 825 | # however this does not guarantee correct behavior here as if time |
| 826 | # continues to not pass, it will try to reconnect repeatedly until |
| 827 | # these timestamps diverge, so in that sense using > is safer. Per |
| 828 | # https://stackoverflow.com/a/1938096/34549, Windows time.time() may be |
| 829 | # within 16 milliseconds accuracy, so unit tests for connection |
| 830 | # invalidation need a sleep of at least this long between initial start |
| 831 | # time and invalidation for the logic below to work reliably. |
| 832 | |
| 833 | if self.dbapi_connection is None: |
| 834 | self.info.clear() |
| 835 | self.__connect() |
| 836 | elif ( |
| 837 | self.__pool._recycle > -1 |
| 838 | and time.time() - self.starttime > self.__pool._recycle |
| 839 | ): |
| 840 | self.__pool.logger.info( |
| 841 | "Connection %r exceeded timeout; recycling", |
| 842 | self.dbapi_connection, |
| 843 | ) |
| 844 | recycle = True |
| 845 | elif self.__pool._invalidate_time > self.starttime: |
| 846 | self.__pool.logger.info( |
| 847 | "Connection %r invalidated due to pool invalidation; " |
| 848 | + "recycling", |
| 849 | self.dbapi_connection, |
| 850 | ) |
| 851 | recycle = True |
| 852 | elif self._soft_invalidate_time > self.starttime: |
| 853 | self.__pool.logger.info( |
| 854 | "Connection %r invalidated due to local soft invalidation; " |
| 855 | + "recycling", |
| 856 | self.dbapi_connection, |
| 857 | ) |
| 858 | recycle = True |
| 859 | |
| 860 | if recycle: |
| 861 | self.__close(terminate=True) |
| 862 | self.info.clear() |
| 863 | |
| 864 | self.__connect() |
| 865 | |
| 866 | assert self.dbapi_connection is not None |
| 867 | return self.dbapi_connection |
| 868 | |
| 869 | def _is_hard_or_soft_invalidated(self) -> bool: |
| 870 | return ( |