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